Openlayers 距离环绘制

发布时间 2023-08-04 13:36:44作者: echo_lovely

思路:利用layer的StyleFunction 来使地图移动或者放缩的时候,使圆保持在地图中心


/**
 * 绘制距离环
 * @param {number} distance 每环间隔距离,单位:米
 * @param {array} texts 要显示的内容
 * @description 创建了个layer,然后在layer的styleFunction中做了配置,这里搞了6个环,每两个是一组;搞两个的原因是为了在左侧和右侧都显示当前环的尺寸
 */
export function drawDistanceRing(distance, texts) {
  const map = window.map
  const layer = new VectorLayer({
    source: new VectorSource(),
    zIndex: 999,
    projection: 'EPSG:4326',
    style: function (feature) {
      const center = map.getView().getCenter()
      const proj = map.getView().getProjection()
      const [offsetL1, offsetR1, offsetL2, offsetR2, offsetL3, offsetR3] = calcDistanceRingTextOffset(center, distance * 0.9) // 计算每个环标签像素偏移量
      return [
        new Style({ // 每个style都是一个环
          geometry: circular(center, distance * 1, 128),
          text: new Text({
            text: texts[0],
            font: '14px sans-serif',
            fill: new Fill({
              color: '#e72b19',
            }),
            offsetX: offsetL1[0],
            offsetY: offsetL1[1]
          }),
          stroke: new Stroke({
            color: '#e72b19',
            width: 3
          })
        }),
        new Style({
          geometry: circular(center, distance * 1, 128),
          text: new Text({
            text: texts[0],
            font: '14px sans-serif',
            fill: new Fill({
              color: '#e72b19',
            }),
            offsetX: offsetR1[0],
            offsetY: offsetR1[1]
          }),
          stroke: new Stroke({
            color: '#e72b19',
            width: 3
          })
        }),
        new Style({
          geometry: circular(center, distance * 2, 128),
          text: new Text({
            text: texts[1],
            font: '14px sans-serif',
            fill: new Fill({
              color: '#e72b19',
            }),
            offsetX: offsetL2[0],
            offsetY: offsetL2[1]
          }),
          stroke: new Stroke({
            color: '#e72b19',
            width: 3
          })
        }),
        new Style({
          geometry: circular(center, distance * 2, 128),
          text: new Text({
            text: texts[1],
            font: '14px sans-serif',
            fill: new Fill({
              color: '#e72b19',
            }),
            offsetX: offsetR2[0],
            offsetY: offsetR2[1]
          }),
          stroke: new Stroke({
            color: '#e72b19',
            width: 3
          })
        }),
        new Style({
          geometry: circular(center, distance * 3, 128),
          text: new Text({
            text: texts[2],
            font: '14px sans-serif',
            fill: new Fill({
              color: '#e72b19',
            }),
            offsetX: offsetL3[0],
            offsetY: offsetL3[1]
          }),
          stroke: new Stroke({
            color: '#e72b19',
            width: 3
          })
        }),
        new Style({
          geometry: circular(center, distance * 3, 128),
          text: new Text({
            text: texts[2],
            font: '14px sans-serif',
            fill: new Fill({
              color: '#e72b19',
            }),
            offsetX: offsetR3[0],
            offsetY: offsetR3[1]
          }),
          stroke: new Stroke({
            color: '#e72b19',
            width: 3
          })
        }),
      ]
    }
  })
  
  const feature = new Feature(fromExtent(map.getView().getProjection().getExtent())) // layer得有feature,不然不显示
  layer.getSource().addFeature(feature)

  map.addLayer(layer)
}
/**
 * 移除距离环
 */
export function removeDistanceRing(layer) {
  if (layer) {
    layer.getSource().clear()
    window.map.removeLayer(layer)
  }
}
/**
 * 计算距离环文字偏移量
 * @param {array} location 距离环圆心坐标
 * @param {number} distance 每个环间距
 * @returns 六个环偏移量
 */
function calcDistanceRingTextOffset(location, distance) {
  const point = turf.point(location) // 用到了turf这个库 
  const destination1R = turf.destination(point, distance, 90, 'meters' ).geometry.coordinates
  const destination1L = turf.destination(point, distance, 270, 'meters' ).geometry.coordinates
  const destination2R = turf.destination(point, distance * 2, 90, 'meters' ).geometry.coordinates
  const destination2L = turf.destination(point, distance * 2, 270, 'meters' ).geometry.coordinates
  const destination3R = turf.destination(point, distance * 3, 90, 'meters' ).geometry.coordinates
  const destination3L = turf.destination(point, distance * 3, 270, 'meters').geometry.coordinates
  
  const pixelCenter = getPixelFromCoordinate(location)
  const pixel1R = getPixelFromCoordinate(destination1R)
  const pixel1L = getPixelFromCoordinate(destination1L)
  const pixel2R = getPixelFromCoordinate(destination2R)
  const pixel2L = getPixelFromCoordinate(destination2L)
  const pixel3R = getPixelFromCoordinate(destination3R)
  const pixel3L = getPixelFromCoordinate(destination3L)
  
  const offsetR1 = [pixel1R[0] - pixelCenter[0] - 5, pixel1R[1] - pixelCenter[1]]
  const offsetL1 = [pixel1L[0] - pixelCenter[0], pixel1L[1] - pixelCenter[1]]
  const offsetR2 = [pixel2R[0] - pixelCenter[0], pixel2R[1] - pixelCenter[1]]
  const offsetL2 = [pixel2L[0] - pixelCenter[0], pixel2L[1] - pixelCenter[1]]
  const offsetR3 = [pixel3R[0] - pixelCenter[0], pixel3R[1] - pixelCenter[1]]
  const offsetL3 = [pixel3L[0] - pixelCenter[0], pixel3L[1] - pixelCenter[1]]
  return [offsetL1, offsetR1, offsetL2, offsetR2, offsetL3, offsetR3]
}

效果图:
image