当前位置: 首页 > news >正文

OpenLayers总结3

一、 静态测距

1.原理

静态测距主要是针对地图上已有的矢量要素(如线要素),利用 OpenLayers 提供的几何计算函数来获取其长度。在实际操作中,先加载包含几何要素的 GeoJSON 数据到矢量图层,当鼠标指针移动到要素上时,获取该要素的几何信息,再调用 getLength 函数计算其长度。

2.代码实现步骤及注释

// 引入必要的模块
import VectorLayer from "ol/layer/Vector.js";
import VectorSource from "ol/source/Vector";
import GeoJSON from "ol/format/GeoJSON.js";
import { getLength } from "ol/sphere";
import Map from "ol/Map";

// 创建地图实例
const map = new Map({
  target: "map", // 指定地图要渲染到的 HTML 元素的 ID
  // 其他地图配置...
});

// 创建一个矢量图层,用于显示包含几何要素的数据
const chinaLayer = new VectorLayer({
  // 配置矢量数据源
  source: new VectorSource({
    // 从远程 URL 加载 GeoJSON 数据
    url: "https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000",
    // 指定数据的格式为 GeoJSON
    format: new GeoJSON(),
  }),
});

// 将矢量图层添加到地图上
map.addLayer(chinaLayer);

// 监听地图的鼠标移动事件
map.on("pointermove", (e) => {
  // 获取鼠标当前位置的坐标
  const coord = e.coordinate;
  // 获取当前坐标处的所有要素
  const features = chinaLayer.getSource().getFeaturesAtCoordinate(coord);

  // 如果当前坐标处存在要素
  if (features.length > 0) {
    // 获取第一个要素的几何信息
    const chianGeo = features[0].getGeometry();
    // 使用 getLength 函数计算几何要素的长度,指定投影方式为 EPSG:4326
    const length = getLength(chianGeo, {
      projection: "EPSG:4326",
    });
    // 将长度转换为千米并保留两位小数
    const lengthInKm = (length / 1000).toFixed(2);
    // 输出计算得到的长度,这里可以根据需求进行其他处理,如显示在页面上
    console.log(`长度: ${lengthInKm}km`);
  }
});

二、 交互测距

1.原理

交互测距允许用户在地图上通过手动绘制几何图形(如线段)来实时计算其长度。借助 OpenLayers 的 Draw 交互类,用户可以在地图上绘制图形,同时监听绘制过程中的 drawstartdrawend 事件,在事件处理函数中获取绘制的几何信息并计算长度。

2.代码实现步骤及注释

// 引入必要的模块
import Draw from "ol/interaction/Draw";
import VectorLayer from "ol/layer/Vector.js";
import VectorSource from "ol/source/Vector";
import { getLength } from "ol/sphere";
import Map from "ol/Map";

// 创建地图实例
const map = new Map({
  target: "map", // 指定地图要渲染到的 HTML 元素的 ID
  // 其他地图配置...
});

// 创建一个矢量图层,用于显示用户绘制的图形
const drawLayer = new VectorLayer({
  // 配置矢量数据源
  source: new VectorSource(),
});

// 将绘制图层添加到地图上
map.addLayer(drawLayer);

// 初始化绘制交互对象为 null
let draw = null;
// 获取 HTML 中用于选择绘制类型的下拉框元素
const select = document.querySelector("#type-select");

// 监听下拉框的 change 事件
select.addEventListener("change", function () {
  // 如果之前已经存在绘制交互,移除它
  if (draw) {
    map.removeInteraction(draw);
    draw = null;
  }

  // 如果选择的是绘制线段
  if (this.value === "line") {
    // 创建绘制交互对象,指定绘制类型为 LineString,并将绘制结果添加到 drawLayer 的数据源中
    draw = new Draw({
      type: "LineString",
      source: drawLayer.getSource(),
    });

    // 监听绘制结束事件
    draw.on("drawend", (e) => {
      // 获取绘制结束时的要素
      const f = e.feature;
      // 获取要素的几何信息
      const g = f.getGeometry();
      // 计算几何要素的长度,转换为千米并保留两位小数
      const length = (getLength(g, { projection: "EPSG:4326" }) / 1000).toFixed(2);
      // 输出线段的总长度
      console.log(`线段总长度: ${length}km`);
    });

    // 监听绘制开始事件
    draw.on("drawstart", function (e) {
      // 获取正在绘制的要素
      const sketch = e.feature;
      // 监听要素几何信息的变化事件
      sketch.getGeometry().on("change", function (e) {
        // 获取变化后的几何信息
        const g = e.target;
        // 计算当前绘制的线段长度,转换为千米并保留两位小数
        const length = (getLength(g, { projection: "EPSG:4326" }) / 1000).toFixed(2);
        // 输出当前线段的长度
        console.log(`当前长度: ${length}km`);
      });
    });

    // 将绘制交互添加到地图上
    map.addInteraction(draw);
  }
});

三、热力图层

1.原理

热力图层用于将一组点要素以热力图的形式展示,通过不同的颜色强度来表示点的密度分布。首先需要创建点要素,然后将这些要素添加到矢量数据源中,最后使用 Heatmap 类创建热力图层并添加到地图上。

2.代码实现步骤及注释

// 引入必要的模块
import Heatmap from "ol/layer/Heatmap.js";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
import { Point } from "ol/geom";
import Map from "ol/Map";

// 创建地图实例
const map = new Map({
  target: "map", // 指定地图要渲染到的 HTML 元素的 ID
  // 其他地图配置...
});

// 定义一组点数据,包含名称和坐标
const points = [
  { name: "黄鹤楼", coords: [114.3162, 30.5278] },
  // 其他点数据...
];

// 将点数据转换为 OpenLayers 的 Feature 对象数组
const features = points.map((point) => {
  return new Feature({
    // 创建 Point 几何对象,指定坐标
    geometry: new Point(point.coords),
    // 为要素添加名称属性
    name: point.name,
  });
});

// 创建热力图层
const heatLayer = new Heatmap({
  // 配置矢量数据源,将 Feature 数组添加到数据源中
  source: new VectorSource({
    features: features,
  }),
});

// 将热力图层添加到地图上
map.addLayer(heatLayer);

 四、要素动画

1.原理

要素动画通过不断更新要素的位置或样式来实现动态效果。可以手动计算要素的位置,也可以使用第三方库(如 ol-ext)提供的动画类。在这个例子中,我们使用 ol_featureAnimation_Path 类创建路径动画,让一个点要素沿着指定的路径移动。

2.代码实现步骤及注释

// 引入必要的模块
import Feature from "ol/Feature";
import { LineString, Point } from "ol/geom";
import Style from "ol/style/Style";
import Stroke from "ol/style/Stroke";
import Icon from "ol/style/Icon";
import CircleStyle from "ol/style/Circle.js";
import Fill from "ol/style/Fill";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Map from "ol/Map";
import ol_featureAnimation_Path from "ol-ext/featureanimation/Path.js";

// 创建地图实例
const map = new Map({
  target: "map", // 指定地图要渲染到的 HTML 元素的 ID
  // 其他地图配置...
});

// 定义三个城市的坐标,用于创建路径
const cityPoints = [
  [114.3055, 30.5928], // 武汉
  [113.6504, 34.7638], // 郑州
  [116.4074, 39.9042], // 北京
];

// 创建从武汉到郑州的连续离散点,共 200 个
const points = [];
for (let i = 0; i < 200; i++) {
  const ratio = i / 200;
  const point = [
    cityPoints[0][0] * (1 - ratio) + cityPoints[1][0] * ratio,
    cityPoints[0][1] * (1 - ratio) + cityPoints[1][1] * ratio,
  ];
  points.push(point);
}

// 创建从郑州到北京的连续离散点,共 200 个
for (let i = 0; i < 200; i++) {
  const ratio = i / 200;
  const point = [
    cityPoints[1][0] * (1 - ratio) + cityPoints[2][0] * ratio,
    cityPoints[1][1] * (1 - ratio) + cityPoints[2][1] * ratio,
  ];
  points.push(point);
}

// 创建表示路径的要素
const lineFeature = new Feature({
  type: "route", // 要素类型为路径
  // 创建 LineString 几何对象,指定路径的坐标数组
  geometry: new LineString(points),
});

// 创建表示起始点的要素
const startMarker = new Feature({
  type: "icon", // 要素类型为图标
  // 创建 Point 几何对象,指定起始点的坐标
  geometry: new Point(points[0]),
});

// 创建表示结束点的要素
const endMarker = new Feature({
  type: "icon", // 要素类型为图标
  // 创建 Point 几何对象,指定结束点的坐标
  geometry: new Point(points[points.length - 1]),
});

// 创建表示移动点的要素
const dotMarker = new Feature({
  type: "dot", // 要素类型为点
  // 创建 Point 几何对象,指定移动点的初始坐标
  geometry: new Point(points[0]),
});

// 定义不同类型要素的样式
const styles = {
  route: new Style({
    // 为路径要素设置描边样式,颜色为红色,宽度为 5
    stroke: new Stroke({
      color: "red",
      width: 5,
    }),
  }),
  icon: new Style({
    // 为图标要素设置图标样式,指定图标的 URL 和锚点
    image: new Icon({
      src: "/location.png",
      anchor: [0.5, 1],
    }),
  }),
  dot: new Style({
    // 为点要素设置圆形样式,半径为 5,填充颜色为绿色
    image: new CircleStyle({
      radius: 5,
      fill: new Fill({
        color: "green",
      }),
    }),
  }),
};

// 创建矢量图层
const vectorLayer = new VectorLayer({
  // 配置矢量数据源,将路径、起始点、结束点和移动点要素添加到数据源中
  source: new VectorSource({
    features: [lineFeature, startMarker, endMarker, dotMarker],
  }),
  // 根据要素的类型返回对应的样式
  style: function (feature) {
    return styles[feature.get("type")];
  },
});

// 将矢量图层添加到地图上
map.addLayer(vectorLayer);

// 获取 HTML 中用于控制动画速度的输入框元素
const speedBtn = document.querySelector("#speed");
// 获取 HTML 中用于启动动画的按钮元素
const startBtn = document.querySelector("#start-btn");

// 初始化动画对象为 null
let anim;

// 监听启动按钮的点击事件
startBtn.addEventListener("click", startAnimation);

// 启动动画的函数
function startAnimation() {
  // 更新按钮文本,表示动画正在进行
  startBtn.innerHTML = "动画进行中";
  // 创建路径动画对象,指定路径、速度和持续时间
  anim = new ol_featureAnimation_Path({
    path: lineFeature,
    speed: parseFloat(speedBtn.value) * 0.0001,
    duration: 2000,
  });
  // 在矢量图层上对移动点要素启动动画
  vectorLayer.animateFeature(dotMarker, anim);
  // 监听动画结束事件
  anim.on("animationend", function () {
    // 更新按钮文本,表示动画已结束
    startBtn.innerHTML = "开始动画";
  });
}

相关文章:

  • [hgame 2025] week2 pwn/crypto
  • ShenNiusModularity项目源码学习(9:项目结构)
  • ActiveMQ之VirtualTopic
  • LM_Funny-2-01 递推算法:从数学基础到跨学科应用
  • DeepSeek V3原理
  • 代码随想录day14
  • SolidWorks速成教程P4-4【装配体 | 第四节】——装配体内修改模型编辑配合方法配合报错的解决方法
  • 在华为云部署应用,通过阿里云代理调用第三方接口的利弊与解决方案
  • module ‘cv2.dnn‘ has no attribute ‘DictValue‘解决办法
  • 电力交易员需要哪些证书
  • 安装MinkowskiEngine记录
  • 解决DeepSeek服务器繁忙的有效方法
  • mapbox基础,使用geojson加载circle圆点图层
  • 燧光 XimmerseMR SDK接入Unity
  • nginx 搭建
  • vue中为组建添加样式的方式
  • AI 百炼成神:逻辑回归, 垃圾邮件分类
  • 深入浅出gRPC:原理、HTTP/2协议与四种通信模式详解
  • 【复现DeepSeek-R1之Open R1实战】系列6:GRPO源码逐行深度解析(上)
  • 单证处理新突破:外贸软件助力释放人力价值
  • 19岁女生注射头孢离世后续:院方道歉,医生停职,监管介入
  • 昆明阳宗海风景名胜区19口井违规抽取地热水,整改后用自来水代替温泉
  • 常州市委原常委、组织部部长陈翔调任江苏省民宗委副主任
  • 特朗普政府拟终止太空污染研究,马斯克旗下太空公司将受益
  • “20后”比“60后”更容易遭遇极端气候事件
  • 王日春已任教育部社会科学司司长,此前系人教社总编辑