vue + openlayer 按路径移动

示例

创建一个方形的规矩,并让点按轨迹移动。效果如下:
在这里插入图片描述

源代码

<template>
  <div>
    <div id="map" class="map"></div>
    <button id="start-animation" ref="startButton">Start Animation</button>
  </div>
</template>

<script>
import "ol/ol.css";
import "@/assets/css/map.css";
import { Map, View, Feature } from "ol";
import { Circle as CircleStyle, Fill, Icon, Stroke, Style } from "ol/style";
import { OSM, Vector as VectorSource } from "ol/source";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { getVectorContext } from "ol/render";
import { LineString, Point } from "ol/geom";
import { ref } from "vue";

export default {
  setup(props) {
    const map = ref(null);
    const startButton = ref(null);
    const styles = {
      route: new Style({
        stroke: new Stroke({
          width: 6,
          color: [237, 212, 0, 0.8],
        }),
      }),
      icon: new Style({
        image: new Icon({
          anchor: [0.5, 1],
          src: "https://openlayers.org/en/latest/examples/data/icon.png",
        }),
      }),
      geoMarker: new Style({
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({ color: "red" }),
          stroke: new Stroke({
            color: "white",
            width: 2,
          }),
        }),
      }),
    };

    return { map, styles, startButton };
  },

  data() {
    return {
      speedInput: 5,
      animating: false,
      distance: 0,
      lastTime: null,
      position: null,
      geoMarker: null,
      vectorLayer: null,
      route: null,
    };
  },

  mounted() {
    this.map = new Map({
      layers: [
        new TileLayer({
          source: new OSM(),
        }),
      ],
      target: "map",
      view: new View({
        center: [-5645116.561407479, -3504865.8960142885],
        zoom: 10,
      }),
    });

    this.createRoute();

    var that = this;
    that.startButton.addEventListener("click", function () {
      if (that.animating) {
        that.stopAnimation();
      } else {
        that.startAnimation();
      }
    });
  },

  methods: {
    moveFeature(event) {
      const speed = 20;
      const time = event.frameState.time;
      const elapsedTime = time - this.lastTime;
      this.distance = (this.distance + (speed * elapsedTime) / 1e5) % 2;
      this.lastTime = time;

      //按比例获取坐标位置
      const currentCoordinate = this.route.getCoordinateAt(
        this.distance > 1 ? 2 - this.distance : this.distance
      );
      this.position.setCoordinates(currentCoordinate);
      const vectorContext = getVectorContext(event);
      vectorContext.setStyle(this.styles.geoMarker);
      vectorContext.drawGeometry(this.position);
      // tell OpenLayers to continue the postrender animation
      this.map.render();
    },

    startAnimation() {
      this.animating = true;
      this.lastTime = Date.now();
      this.startButton.textContent = "Stop Animation";
      this.vectorLayer.on("postrender", this.moveFeature);
      // hide geoMarker and trigger map render through change event
      this.geoMarker.setGeometry(null);
    },

    stopAnimation() {
      this.animating = false;
      this.startButton.textContent = "Start Animation";

      // Keep marker at current animation position
      this.geoMarker.setGeometry(this.position);
      this.vectorLayer.un("postrender", this.moveFeature);
    },

    createRoute() {
      var that = this;

      var coordinates = [
        [-5701523.274225562, -3508003.9130105707],
        [-5570600.171389932, -3508003.9130105707],
        [-5570600.171389932, -3522590.9336281433],
        [-5701523.274225562, -3522590.9336281433],
        [-5701523.274225562, -3508003.9130105707],
      ];

      that.route = new LineString(coordinates);

      const routeFeature = new Feature({
        type: "route",
        geometry: that.route,
      });

      const startMarker = new Feature({
        type: "icon",
        geometry: new Point(that.route.getFirstCoordinate()),
      });
      const endMarker = new Feature({
        type: "icon",
        geometry: new Point(that.route.getLastCoordinate()),
      });

      that.position = startMarker.getGeometry().clone();
      that.geoMarker = new Feature({
        type: "geoMarker",
        geometry: that.position,
      });

      that.vectorLayer = new VectorLayer({
        source: new VectorSource({
          features: [routeFeature, that.geoMarker, startMarker, endMarker],
        }),
        style: function (feature) {
          return that.styles[feature.get("type")];
        },
      });

      that.map.addLayer(that.vectorLayer);
    },
  },
};
</script>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值