GIS地图:测量

前言

openlayers还提供了测量相关的api,可在地图上测量路线的长度,以及区域的面积。通过此api,可开发一个测量工具,进行长度和面积的测量

一、创建图层

  import Draw, { createRegularPolygon } from 'ol/interaction/Draw.js';
  import { getArea, getLength } from 'ol/sphere.js';
  import Fill from 'ol/style/Fill.js';
  import Stroke from 'ol/style/Stroke.js';

  drawSource.value = new VectorSource({ wrapX: false });
  const drawLayer = new VectorLayer({
    source: drawSource.value,
    style() {
      return new Style({
        fill: new Fill({
          color: 'rgba(0, 176, 255, 0.4)', // 设置填充颜色和透明度
        }),
        stroke: new Stroke({
          color: 'rgba(0, 176, 255, 1)',
          width: 2,
        }),
      });
    },
  });
  map.instance.addLayer(drawLayer)

二、绘制并测量

function handleSelectTool(key: any) {
  if (draw.value) {
    map.instance.removeInteraction(draw.value);
  }

  switch (key) {
    case 'area': {
      measure('Polygon'); // 测量区域大小

      break;
    }
    
    case 'distance': {
      measure('LineString');  // 测量路线长度

      break;
    }
    // No default
  }
}
const measureTooltipElement = ref(null);
const measureTooltip = ref(null);
const sketch = ref(null);
// 绘制方法
function measure(measureType: any) {
  // 创建提示框(实时显示测量结果)
  createMeasureTooltip();
  draw.value = new Draw({
    source: drawSource.value,
    type: measureType,
    style: {
      'fill-color': 'rgba(0, 176, 255, 0.4)',
      'stroke-color': 'rgba(0, 176, 255, 1)',
      'stroke-width': 2,
      'circle-radius': 6,
      'circle-fill-color': 'rgba(0, 176, 255, 1)',
      'circle-stroke-color': 'rgba(255, 255, 255, 1)',
      'circle-stroke-width': 1,
    },
  });
  map.instance?.addInteraction(draw.value);

  let listener;
  // 开始绘制的监听
  draw.value.on('drawstart', (evt: any) => {
    // set sketch
    // 获取绘制的feature
    sketch.value = evt.feature;

    /** @type {module:ol/coordinate~Coordinate|undefined} */
    let tooltipCoord = evt.coordinate;

    // 监听绘制feature的大小的改变
    listener = sketch.value.getGeometry().on('change', (evt: any) => {
      const geom = evt.target;
      let output;
      if (geom instanceof Polygon) {
        // 判断,绘制的是一个面积,计算面积的大小
        output = formatArea(geom);
        tooltipCoord = geom.getInteriorPoint().getCoordinates();
      } else if (geom instanceof LineString) { 
        // 判断绘制的是路径,计算路径的长度
        output = formatLength(geom);
        tooltipCoord = geom.getLastCoordinate();
      }
      // 将计算结果,显示到弹出层中
      measureTooltipElement.value.innerHTML = output;
      measureTooltip.value.setPosition(tooltipCoord);
    });
  });

  draw.value.on('drawend', () => {
    measureTooltipElement.value.className = 'tooltip tooltip-static';
    measureTooltip.value.setOffset([0, -7]);
    // unset sketch
    sketch.value = null;
    // unset tooltip so that a new one can be created
    measureTooltipElement.value = null;
    unByKey(listener);
    map.instance.removeInteraction(draw.value);
  });

  function createMeasureTooltip() {
    if (measureTooltipElement.value) {
      measureTooltipElement.value.remove();
    }
    measureTooltipElement.value = document.createElement('div');
    measureTooltipElement.value.className = 'tooltip tooltip-measure';
    measureTooltip.value = new Overlay({
      element: measureTooltipElement.value,
      offset: [0, -15],
      positioning: 'bottom-center',
    });
    map.instance.addOverlay(measureTooltip.value);
    measureTooltipArray.value.push(measureTooltip.value);
  }
}
// 核心api,计算路径的长度
const formatLength = (line: any) => {
  // getLength是openlayers提供的api
  const length = getLength(line, { projection: 'EPSG:4326' });
  const output =
    length > 100
      ? `${Math.round((length / 1000) * 100) / 100} ` + `km`
      : `${Math.round(length * 100) / 100} ` + `m`;
  return output;
};
// 核心api,计算面积的大小
const formatArea = (polygon: any) => {
  // getArea是openlayers提供的api
  const area = getArea(polygon, { projection: 'EPSG:4326' });
  const output =
    area > 10_000
      ? `${Math.round((area / 1_000_000) * 100) / 100} ` + `km<sup>2</sup>`
      : `${Math.round(area * 100) / 100} ` + `m<sup>2</sup>`;
  return output;
};

测量长度或面积的时候,如果使用的不是EPSG:3857(默认)坐标系,则需要设置成当前地图的坐标系,否则会导致计算不准确。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容