vue3基于openlayers 实现多轨迹扩散效果

vue3基于openlayers 实现多轨迹扩散效果
思路:以点到点的轨迹连线,一个点沿着轨迹移动,多条线就绘制多条线移动,线太多就会卡顿

// 热力图图层,包含点、线、热力点
function drawHeatmapLayer(point) {
  animating.value = props.points.length > 0;
  let featureLine = new LineString(point);
  let routeFeature = new Feature({
    type: "line",
    geometry: featureLine,
  });
  const startMarker = new Feature({
    geometry: new Point(featureLine.getFirstCoordinate()),
  });
  const endMarker = new Feature({
    geometry: new Point(featureLine.getLastCoordinate()),
  });
  const position = startMarker.getGeometry().clone();
  // 热力点
  var heatPointFeature = new Feature({
    geometry: position,
  });
  layer.value.getSource().addFeature(heatPointFeature);
  const styles = {
    line: new Style({
      stroke: new Stroke({
        width: 3,
        color: "transparent",
      }),
    }),
  };
  vectorLayer = new VectorLayer({
    source: new VectorSource({
      features: [routeFeature, startMarker, endMarker],
    }),
    style: function(feature) {
      return styles[feature.get("type")];
    },
  });
  MapRef.value.map.addLayer(vectorLayer);
  mapAnimation(featureLine, position);
}

// 获取所有热力点的中心点
function getCenterPoint(geoCoordinateList) {
  let X = 0;
  let Y = 0;
  let total = geoCoordinateList.length;
  for (const g of geoCoordinateList) {
    X += g[0];
    Y += g[1];
  }
  X = X / total;
  Y = Y / total;
  return [X, Y];
}
// 改变地图中心点
function getHeatPointInfo() {
  let heatMapFeaturesPoints = [];
  layer.value
    .getSource()
    .getFeatures()
    .forEach((item) => {
      heatMapFeaturesPoints.push(item.getGeometry().getCoordinates());
    });
  // 当前的位置范围
  let positionRange = refreshMapLocation();
  let heatMapCenter = getCenterPoint(heatMapFeaturesPoints);
  if (
    heatMapCenter[1] > positionRange.currentExtentRight[1] ||
    heatMapCenter[1] < positionRange.currentExtentLeft[1] ||
    heatMapCenter[0] > positionRange.currentExtentRight[0] ||
    heatMapCenter[0] < positionRange.currentExtentLeft[0]
  ) {
    // 热力图中心点超出屏幕范围,改变当前中心点为地图中心
    centerPoint.value = heatMapCenter;
    // MapRef.value
    const zoom = MapRef.value.getZoomSize();
    MapRef.value.moveTo(heatMapCenter, 10, "inAndOut", {
      zoom: zoom,
    });
  }
}
// 地图动画
function mapAnimation(featureLine, position) {
  let distance = 0;
  function moveFeature() {
    if (isAnimating) {
      const speed = props.spreed;
      let speedRondom = parseFloat(Math.random().toFixed(3)) * 100;
      distance = (distance + (speed * speedRondom) / 1e6) % 2;
      const currentCoordinate = featureLine.getCoordinateAt(distance);
      if (distance > 1) {
        stopAnimation();
      } else {
        position.setCoordinates(currentCoordinate);
      }
    }
  }
  if (animating.value) {
    startAnimation();
  } else {
    stopAnimation();
  }

  function startAnimation() {
    vectorLayer.on("postrender", moveFeature);
    vectorLayer.dispatchEvent("postrender");
  }

  function stopAnimation() {
    animating.value = false;
    vectorLayer.on("postrender", moveFeature);
  }
}

function initHeatmapLayer() {
  isAnimating = true;
  refreshMapLocation();
  layer.value = new HeatmapLayer({
    source: new VectorSource(),
    blur: props.blur,
    radius: props.radius,
    gradient: props.colors,
  });
  addSubLayer();
  props.points.forEach((item) => {
    drawHeatmapLayer(item);
  });
}

// 添加图层到map
function addSubLayer() {
  const map = MapRef.value.map;
  if (layer.value) {
    map.addLayer(layer.value);
  }
}

function refreshMapLocation() {
  // 获取视图对角位置
  let postions = MapRef.value.getDotSize();
  // 计算出视图经度长度
  let Long = (postions[2] - postions[0]) / 2;
  // 计算出视图纬度长度
  let Lat = (postions[3] - postions[1]) / 2;
  //计算出当前范围内的经度纬度(右)
  let currentExtentRight = [
    centerPoint.value[0] + Long,
    centerPoint.value[1] + Lat,
  ];
  //计算出当前范围内的经度纬度(左)
  let currentExtentLeft = [
    centerPoint.value[0] - Long,
    centerPoint.value[1] - Lat,
  ];
  return {
    currentExtentRight,
    currentExtentLeft,
  };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值