openLayers实现动态路径(可控)

110 阅读3分钟
<template>
  <div id="map-box">
    <div id="menu">
      <label for="speed">
        speed:&nbsp;
        <input id="speed" type="range" min="1000" max="10000" step="1000" value="1000">
      </label>
      <button id="start-animation" @click="startAnimation">开始</button>
      <button id="pause-animation" @click="pauseAnimation">暂停</button>
      <button id="continue-animation" @click="continueAnimation">继续</button>
      <button id="stop-animation" @click="stopAnimation">结束</button>
    </div>
  </div>
</template>

<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import { fromLonLat } from 'ol/proj';
import XYZ from 'ol/source/XYZ';
import { Style, Stroke, Icon } from 'ol/style'
import { LineString, Point } from 'ol/geom';
import Feature from 'ol/Feature.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import { testData } from './mockData.js'
var geoMarker;
var moveFeature;
let vectorLayer;
let routeFeature;
let startMarker;
let endMarker;
let animating;
let elapsedTime
let speed;
export default {
  name: 'mapBox',
  data() {
    return {
      map: null,
      timer: null,
      animating: false,
      timerFlag: false,
      routerIndex: 0,
      pointLayer: null
    }

  },
  methods: {
    initMap() {
      this.map = new Map({
        layers: [
          new TileLayer({
            source: new XYZ({
              url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
            }),
          })
        ],
        view: new View({
          center: fromLonLat([121.061162, 30.628472]), // 成都
          zoom: 18, // 设置初始化时的地图缩放层级
          projection: 'EPSG:3857', // 坐标系
          maxZoom: 18, // 最大缩放层级
          minZoom: 4, // 最小缩放层级
        }),
        target: 'map-box', // 地图的dom
      });
    },
    // 初始化路径
    initLineLayer() {
      let that = this
      var Coordinates = testData.map((item) => {
        return fromLonLat(item)
      })
      var route = new LineString(Coordinates);
      //获取直线的坐标
      var routeCoords = route.getCoordinates();
      console.log('routeCoords: ', routeCoords);
      var routeLength = routeCoords.length;

      routeFeature = new Feature({
        type: 'route',
        geometry: route
      });
      geoMarker = new Feature({
        type: 'geoMarker',
        geometry: new Point(routeCoords[0])
      });
      startMarker = new Feature({
        type: 'icon',
        geometry: new Point(routeCoords[0])
      });
      endMarker = new Feature({
        type: 'icon',
        geometry: new Point(routeCoords[routeLength - 1])
      });
      var styles = {
        'route': new Style({
          //轨迹线
          stroke: new Stroke({
            width: 6,
            color: 'transparent'
          })
        }),
        'icon': new Style({
          image: new Icon({
            // anchor: [0.5, 1],
            src: require('/public/终点.png'),
            scale: 0.1, //图标缩放比例
          })
        }),
        'geoMarker': new Style({
          image: new Icon( /** @type {olx.style.IconOptions} */({
            // anchor: [0.5, 60],
            anchorOrigin: 'top-right',
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            offsetOrigin: 'top-right', //偏移原点-偏移起点位置的方向
            // offset:[0,10],
            scale: 0.3, //图标缩放比例
            // opacity: 0.75, //透明度
            rotateWithView: false,
            rotation: -Math.atan2(routeCoords[0][1] - routeCoords[1][1], routeCoords[0][
              0
            ] - routeCoords[1][0]), //旋转图片
            src: require('/public/plane.png') //图标的url
          })),
        })
      };
      animating = false;
      // var now;


      // var startButton = document.getElementById('start-animation')
      // var pauseButton = document.getElementById('pause-animation')
      // var continueButton = document.getElementById('continue-animation')
      // var stopButton = document.getElementById('stop-animation')
      vectorLayer = new VectorLayer({
        source: new VectorSource({
          features: [routeFeature, geoMarker, startMarker, endMarker]
        }),
        style: function (feature) {
          //如果动画是激活的就隐藏geoMarker
          if (animating && feature.get('type') === 'geoMarker') {
            return null;
          }
          return styles[feature.get('type')];
        }
      })
      this.map.addLayer(vectorLayer)
      //要素移动
      moveFeature = function () {
        if (!vectorLayer.getVisible()) {
          vectorLayer.setVisible(true)
        }

        elapsedTime++ // elapsedTime 已过时间

        //通过增加速度,来获得lineString坐标
        that.routerIndex = Math.round(speed * elapsedTime / 1000);
        console.log('elapsedTime', elapsedTime);
        if (that.routerIndex >= routeLength) {
          clearInterval(that.timer);
          return;
        }

        var x, y, rotation, carStyle;
        console.log('that.routerIndex: ', that.routerIndex);
        if (routeCoords[that.routerIndex] && routeCoords[that.routerIndex + 1]) {
          x = routeCoords[that.routerIndex][0] - routeCoords[that.routerIndex + 1][0];
          y = routeCoords[that.routerIndex][1] - routeCoords[that.routerIndex + 1][1];
          rotation = Math.atan2(y, x);
          //console.log("***********",rotation);
          // carStyle = new ol.style.Style({
          //     image: new ol.style.Icon({
          //         src: './img/环卫车轨迹.png', //图标的url,
          //         rotateWithView: false,
          //         rotation: Math.atan2(1, 0) - rotation,
          //         scale: 0.5,
          //     })
          // });

          // var currentPoint = new ld.geom.Point(routeCoords[index]);
          // var feature = new ld.Feature(currentPoint);

        } else {
          rotation = 0
        }
        carStyle = new Style({
          image: new Icon({
            src: require('/public/plane.png'), //图标的url,
            rotateWithView: false,
            rotation: Math.atan2(1, 0) - rotation,
            scale: 0.3,
          })
        });
        var line = new Feature({
          geometry: new LineString(routeCoords.slice(0, that.routerIndex + 1))
        })
        var lineStyle = new Style({
          stroke: new Stroke({
            width: 6,
            color: 'blue'
          })
        })
        line.setStyle(lineStyle)
        var line1 = new Feature({
          geometry: new LineString(routeCoords.slice(that.routerIndex))
        })
        var lineStyle1 = new Style({
          stroke: new Stroke({
            width: 6,
            color: 'transparent'
          })
        })
        line1.setStyle(lineStyle1)
        var currentPoint = new Point(routeCoords[that.routerIndex])
        // 添加矢量元素
        var feature = new Feature(currentPoint)
        vectorLayer.getSource().clear()
        feature.setStyle(carStyle)

        // vectorLayer.getSource().addFeature(routeFeature)
        vectorLayer.getSource().addFeature(startMarker)
        vectorLayer.getSource().addFeature(endMarker)
        vectorLayer.getSource().addFeature(feature)
        vectorLayer.getSource().addFeature(line)
        vectorLayer.getSource().addFeature(line1)


        // content.textContent = gpsPoints[index].gpsTime;
        // popup.setPosition(routeCoords[index]);
        //继续动画效果
        that.map.render();


      };
    },
    startAnimation() {
      // 清除点位
      this.pointLayer.getSource().clear()

      animating = true
      // startTime = new Date().getTime()
      var speedInput = document.getElementById('speed')
      speed = speedInput.value
      console.log('speed', speed);
      // 隐藏geoMarker
      geoMarker.changed()
      // map.getView().setCenter([113.88170241890477, 34.49780059604906])
      // 添加事件,地图渲染时触发
      if (this.timer) {
        clearInterval(this.timer)
      }
      this.timer = setInterval(() => {
        moveFeature()
      }, 1000)
      elapsedTime = 0
    },
    stopAnimation() {
      // 清除点位
      this.pointLayer.getSource().clear()
      clearInterval(this.timer)
      vectorLayer.getSource().clear()
      vectorLayer.getSource().addFeature(routeFeature)
      vectorLayer.getSource().addFeature(startMarker)
      vectorLayer.getSource().addFeature(endMarker)
    },
    pauseAnimation() {
      clearInterval(this.timer)
      this.timerFlag = true
    },
    continueAnimation() {
      if (this.timerFlag) {
        // map.getView().setCenter(Coordinates[0])
        // 添加事件,地图渲染时触发
        this.timer = setInterval(() => {
          moveFeature()
        }, 60)
      }
      this.timerFlag = false
    },
    initPointLayer() {
      const vectorSource = new VectorSource();
      // const pointFeature = new Feature({
      //   geometry: new Point([longitude, latitude]),
      // });
      // vectorSource.addFeature(pointFeature);
      this.pointLayer = new VectorLayer({
        source: vectorSource,
        style: new Style({
          image: new Icon({
            anchor: [0.5, 1],
            src: require('/public/河湖长水质监测点位点位.png'), // 替换为你的图标文件路径
            scale: 0.1, // 图标缩放比例
          }),
        })


      })
      this.map.addLayer(this.pointLayer)
    },
  },
  watch: {
    routerIndex(val) {
      console.log('val', val);
      let pointFeature = new Feature({
        geometry: new Point(fromLonLat(testData[this.routerIndex])),
      });
      this.pointLayer.getSource().addFeature(pointFeature);
      // vectorSource.addFeature(pointFeature);
    }
  },
  mounted() {
    //初始化地图
    this.initMap()
    this.initPointLayer()
    this.initLineLayer()
  }
}

</script>

<style scoped>
#map-box {
  width: 1920px;
  height: 1080px;
}
</style>