openlayers生成路线-具有动画效果

效果

下面的地图图层屏蔽了,不能展示!所以仅有路线demo
路线动态效果

核心代码

<template>
    <div>
      <div id="map" ref="rootmap"></div>
      <a-button id="searchPath" type="primary" style="z-index:3" @click="searchPath">{{title}}</a-button>
    </div>
</template>

<script>
import "ol/ol.css";
import { Map, View } from "ol";
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style";
import Feature from "ol/Feature";
import VectorTileLayer from "ol/layer/VectorTile";
import { LineString, Polygon, Point } from "ol/geom";
import { Vector as VectorSource } from "ol/source";
import VectorLayer from "ol/layer/Vector";
import {
  defaults as defaultInteractions
} from "ol/interaction";
import {
  defaults as defaultControls,
  MousePosition,
} from "ol/control";
import { getVectorContext } from "ol/render";
import { getAction } from "@/api/manage";
import { getCoors } from "@/utils/coordinateUtil";

export default {
  data() {
    return {
      title: "查看当天轨迹",
      map: null, //地图对象
      pointLayer: null, //路径图层
      isShow: false,
      url: {
        getCoorList: "investigationRecord/getCoorList",
      },
      dataList: null,
      coors: [], //路线坐标
      viaPoint: [], //途经点
      animating: false,
      //路线相关样式
      styles: {
        route: new Style({
          stroke: new Stroke({
            width: 6,
            color: [0, 30, 255],
          }),
        }),
        start: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: [0, 191, 94] }),
            stroke: new Stroke({
              color: "white",
              width: 5,
            }),
          }),
        }),
        end: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: [255, 0, 0] }),
            stroke: new Stroke({
              color: "white",
              width: 5,
            }),
          }),
        }),
        geoMarker: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: [0, 30, 255] }),
            stroke: new Stroke({
              color: "white",
              width: 5,
            }),
          }),
        }),
        viaMarker: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: [0, 30, 255] }),
            stroke: new Stroke({
              color: "white",
              width: 5,
            }),
          }),
        }),
      },
      routeFeature: null,
      geoMarker: null,
      startMarker: null,
      endMarker: null,
      speed: 300, //位移速度
      nowTime: null,
    };
  },
  created() {
    var that = this;
    that.getDatas((coors) => {
      that.routeFeature = new Feature({
        type: "route",
        geometry: new LineString(coors),
      });
      that.geoMarker = new Feature({
        type: "geoMarker",
        geometry: new Point(coors[0]),
      });
      that.startMarker = new Feature({
        type: "start",
        geometry: new Point(coors[0]),
      });
      that.endMarker = new Feature({
        type: "end",
        geometry: new Point(coors[coors.length - 1]),
      });
    });
  },
  methods: {
    //获取记录列表的坐标
    getDatas(callback) {
      var that = this;
      let token = Vue.ls.get("token");
      getAction(this.url.getCoorList, null, token).then((res) => {
        if (res.success) {
          that.dataList = res.result;
          for (let i = 1; i < res.result.length; i++) {
          //获取此次路线的所有坐标点,因为是路线 根据y=ax+b 简单计算求出大约
            var coor = getCoors(
              res.result[i - 1].coordinates.split(",").map(Number),
              res.result[i].coordinates.split(",").map(Number)
            );
            if (i > 0 && i < res.result.length - 1) {
            	//将途经点拿出
              that.viaPoint.push(res.result[i].coordinates.split(","));
            }
            that.coors.push(...coor);
          }
          callback(that.coors);
        }
      });
    },
    searchPath() {
      var that = this;
      if (that.pointLayer == null) {
        that.pointLayer = that.createRouteVector(
          that.routeFeature,
          that.geoMarker,
          that.startMarker,
          that.endMarker
        );
        that.map.addLayer(that.pointLayer);
        //设置地图中心点
        that.map.getView().setCenter(that.coors[0]);
        //开始动画
        that.startAnimation();
        that.title = "取消观看轨迹";
      } else {
      //移除路线图层
        that.map.removeLayer(that.pointLayer);
        that.pointLayer = null;
        that.title = "查看当天轨迹";
      }
    },
    createRouteVector(routeFeature, geoMarker, startMarker, endMarker) {
      var that = this;
      var features = [];
      var viaPoint = that.viaPoint;
      //循环添加途经点feature
      for (var i = 0; i < viaPoint.length; i++) {
        features.push(
          new Feature({
            type: "viaMarker",
            geometry: new Point(viaPoint[i]),
          })
        );
      }
      //添加路线
      features.push(routeFeature)
      //添加沿路线动画
      features.push(geoMarker)
      features.push(startMarker)
      features.push(endMarker)

      return new VectorLayer({
        source: new VectorSource({
          features: features,
        }),
        zIndex: 6,
        style: function (feature) {
          if (that.animating && feature.get("type") === "geoMarker") {
            return null;
          }
          return that.styles[feature.get("type")];
        },
      });
    },
    //进行轨迹流动
    moveFeature: function (event) {
      var vectorContext = getVectorContext(event);
      var frameState = event.frameState;
      if (this.animating) {
        var elapsedTime = frameState.time - this.nowTime;
        var index = Math.round((this.speed * elapsedTime * 2) / 1000);
        if (index >= this.coors.length) {
          this.stopAnimation(true);
          return;
        }
        var currentPoint = new Point(this.coors[index]);
        var feature = new Feature(currentPoint);
        vectorContext.drawFeature(feature, this.styles.geoMarker);
      }
      this.map.render();
    },
    startAnimation() {
      if (this.animating) {
        this.stopAnimation(false);
      } else {
        this.animating = true;
        this.nowTime = new Date().getTime();
        this.geoMarker.setStyle(null);
        this.pointLayer.on("postrender", this.moveFeature);
        this.map.render();
      }
    },
    stopAnimation(ended) {
      this.animating = false;
      var coord = ended ? this.coors[this.coors.length - 1] : this.coors[0];
      var geometry = this.geoMarker.getGeometry();
      geometry.setCoordinates(coord);
      this.startAnimation();
    },
  },
};
</script>

有朋友需要的coordinateUtil,如下:

import {getDistance} from 'ol/sphere';

function getCoors(startCoor, endCoor) {
    var xDis = endCoor[0] - startCoor[0]
    var yDis = endCoor[1] - startCoor[1]
    //计算x坐标的增量
    var xUnitstep = xDis / 2000
    var yUnitstep = yDis / 2000
    var x = startCoor[0];
    var y = startCoor[1];
    var coorArr = []
    for (var i = 0; i <= 2000; i++) {
        x = x + xUnitstep
        y = y + yUnitstep
        coorArr.push([x, y])
    }
    return coorArr;
}

function getCoorsByRtio(ratio, startCoor, endCoor) {
    ratio = ratio*1.60665
    // ratio = Math.pow(ratio,2)/1000
    console.log(ratio)
    var xDis = endCoor[0] - startCoor[0]
    var yDis = endCoor[1] - startCoor[1]
    //计算x坐标的增量
    var xUnitstep = xDis / (ratio )
    var yUnitstep = yDis / (ratio )
    var x = startCoor[0];
    var y = startCoor[1];
    var coorArr = []
    for (var i = 0; i <= (ratio); i++) {
        x = x + xUnitstep
        y = y + yUnitstep
        coorArr.push([x, y])
    }
    return coorArr;
}

function calculateRatio(coors) {
    if (coors.length < 1) {
        return;
    }
    //计算各个线段的距离
    var distance = []; //各个线段路程的集合
    for (var i = 0; i < coors.length - 1; i++) {
        distance.push(Math.floor(sphereDistance(coors[i], coors[i + 1])))
    }
    return distance;
}
//数组去重 方法1
function uniqueBySet(arr) {
    return Array.from(new Set(arr))
}
//数组去重 方法2
function uniqueByMap(arr){
    let map = new Map();
    let array = new Array();
    for(let i =0 ; i<arr.length;i++){
        if(map.has(arr[i].toString())){
            map.set(arr[i].toString(),true);
        }else{
            map.set(arr[i].toString(),false);
            array.push(arr[i])
        }
    }
    return array;
}

//计算2个经纬度点之间的距离
function sphereDistance( coor1, coor2) {
    return getDistance(coor1, coor2);
}

export {
    getCoors,
    calculateRatio,
    getCoorsByRtio,
    uniqueByMap,
    uniqueBySet,
    sphereDistance
}
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qlanto

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值