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 = "开始动画";
  });
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super毛毛穗

今天晚饭加什么?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值