WebGL--vue+openlayers实现轨迹回放动画

vue+openlayers实现轨迹回放动画

效果:
WebGL--vue+openlayers实现轨迹回放动画_第1张图片
代码:

<!--  -->
<template>
  <div class="route-review">
    <button @click="toggleFn">{{ buttonContent }}</button>
    <div id="map"></div>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
// //引入主要组件
// // import { Feature, Map, Overlay, View } from "ol";
import { Map, View, Feature } from "ol";
// //引入layer
import ImageLayer from "ol/layer/Image";
import VectorLayer from "ol/layer/Vector";
// //引入source
import Static from "ol/source/ImageStatic";
import VectorSource from "ol/source/Vector";
// //交互
// import { Draw } from "ol/interaction";
// //其他
import Projection from "ol/proj/Projection";
import { getCenter } from "ol/extent";
import { LineString, Point } from "ol/geom";
import { Style, Stroke, Icon } from "ol/style";
// //import { Style, Icon, Text, Fill, Stroke } from "ol/style";
import { getVectorContext } from "ol/render";
// //导入图片
import mapImage from "@/assets/img/map1.jpg"; //底图
import personImg from "@/assets/img/anchor.png";
// import startImg from "@/assets/img/start.jpeg";
// import endImg from "@/assets/img/end.jpeg";
// //引入图形算法工具类turf
// import * as turf from "@turf/turf";
export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    //这里存放数据
    return {
      map: null,
      //轨迹回放
      routeLayer: null,
      routeSource: new VectorSource(),
      routeCoords: [], //轨迹线路的坐标
      routeLength: 0, //轨迹线路的长度
      //画出轨迹
      routeFeature: null,
      routeStyles: new Style({
        //线的样式
        stroke: new Stroke({
          width: 6,
          color: [237, 212, 0, 0.8],
        }),
      }),
      //人员
      PersonFeature: null, //人物标记
      PersonFeatureStyle: new Style({
        image: new Icon({
          anchor: [0.5, 0.8], // 居中
          scale: 0.8, // 图标缩放比例
          opacit: 1, // 透明度
          src: personImg,
        }),
      }),
      //   //标记
      //   startFeature: null, //开始的标记
      //   startFeatureStyle: new Style({
      //     // 设置开始标记样式
      //     image: new Icon({
      //       anchor: [0.5, 1],
      //       src: startImg,
      //       scale: 0.03, // 图标缩放比例
      //     }),
      //   }),
      //   endFeature: null, //结束的标记
      //   endstartFeatureStyle: new Style({
      //     // 设置结束标记样式
      //     image: new Icon({
      //       anchor: [0.5, 1],
      //       src: endImg,
      //     }),
      //   }),

      //   动画
      isAnimate: false, //是否开始动画
      speed: 2, //速度
      buttonContent: "开始播放",
      now: null, //开始的时间
    };
  },
  //计算属性 类似于data概念
  computed: {},
  //监控data中的数据变化
  watch: {},
  //方法集合
  methods: {
    //初始化地图
    initMap() {
      //限制范围
      let extent = [0, 0, 2560, 1920];
      //投影
      let projection = new Projection({
        //SRS 标识符代码,例如EPSG:4326
        code: "xkcd-image",
        //	单位。必需,除非 定义 PROJ4 投影。code
        units: "pixels",
        //SRS 的有效性范围。
        extent: extent,
      });
      //底图Layers
      let mapLayer = new ImageLayer({
        source: new Static({
          url: mapImage,
          projection: projection,
          imageExtent: extent,
        }),
      });
      //轨迹回放矢量图层
      this.routeLayer = new VectorLayer({
        source: this.routeSource,
      });
      //创建地图
      this.map = new Map({
        target: "map",
        layers: [mapLayer, this.routeLayer],
        view: new View({
          //配置投影
          projection: projection,
          //配置中心
          center: getCenter(extent),
          //配置zoom
          zoom: 2,
          //配置最大zoom
          maxZoom: 10,
        }),
      });
    },
    //获取轨迹数据
    getTrack() {
      //获取接口返回的数据
      let res = [
        [256.83593750000006, 370.91015624999994],
        [261.71875000000006, 425.59765624999994],
        [253.90625000000006, 469.54296875],
        [338.86718750000006, 488.09765625],
        [406.25000000000006, 488.09765625],
        [471.67968750000006, 488.09765625],
        [544.9218750000001, 471.49609375],
        [547.8515625000001, 416.80859374999994],
        [542.9687500000001, 366.02734374999994],
      ];
      //获取到轨迹的坐标及长度(深拷贝)
      this.routeCoords = res.map((item) => {
        return (item = [item[0], item[1]]);
      });
      this.routeLength = this.routeCoords.length;
      //绘制轨迹路线
      this.routeFeature = new Feature(new LineString(this.routeCoords));
      this.routeFeature.setStyle(this.routeStyles); //设置轨迹的样式
      //绘制人员(默认在起始位置)
      this.PersonFeature = new Feature(new Point(this.routeCoords[0]));
      this.PersonFeature.setStyle(this.PersonFeatureStyle);
      //矢量图上展示轨迹
      this.routeLayer
        .getSource()
        .addFeatures([this.routeFeature, this.PersonFeature]);
      //请求地图渲染(在下一个动画帧处)
      //   this.map.render();
    },
    //开始动画
    beginAnimate() {
      if (this.isAnimate) {
        //结束动画
        this.stopAnimate(false);
      } else {
        //开启动画(隐藏小人)
        this.isAnimate = true;
        this.buttonContent = "重新播放";
        this.now = new Date().getTime(); //开始的时间
        //去掉小人
        this.PersonFeature.setStyle(null);
        // postrender在layer渲染后调用轨迹播放
        this.routeLayer.on("postrender", this.moveFeature);
        //请求地图渲染(在下一个动画帧处)。
        this.map.render();
      }
    },
    //结束动画
    stopAnimate(ended) {
      this.isAnimate = false;
      this.buttonContent = "开始播放";
      //动画取消之后设置人物到起点//(动画结束--人物停在最后一个点  动画取消--人物停在起点)
      let ii = ended ? this.routeLength - 1 : 0;
      let coord = this.routeCoords[ii];
      this.PersonFeature.setGeometry(new Point(coord));
      //设置走完最后一个点是否显示
      this.PersonFeature.setStyle(this.createLabelStyle(personImg));
      //删除侦听器
      this.routeLayer.un("postrender", this.moveFeature);
    },
    //轨迹回放
    moveFeature(e) {
      //获取渲染图层的画布
      let vectorContext = getVectorContext(e);
      let frameState = e.frameState;
      console.log("渲染图层的画布", vectorContext);
      console.log("frameState", frameState);
      if (this.isAnimate) {
        //动画开始进入判断
        let elapsedTime = frameState.time - this.now; //经过的时间
        console.log("frameState.time", frameState.time);
        console.log("now", this.now);
        console.log("elapsedTime", elapsedTime);
        let index = Math.round((this.speed * elapsedTime) / 1000);
        console.log("index", index);
        //走完了路线坐标点
        if (index >= this.routeLength) {
          this.stopAnimate();
          return;
        }
        //获取到当前点
        let currentPoint = new Point(this.routeCoords[index]);
        let feature = new Feature(currentPoint);
        vectorContext.drawFeature(feature, this.PersonFeatureStyle); //将要素渲染到画布中。
      }
      //请求地图渲染(在下一个动画帧处)。
      this.map.render();
    },
    //切换按钮
    toggleFn() {
      if (this.buttonContent == "重新播放") {
        this.stopAnimate(false);
      } else {
        this.beginAnimate();
      }
    },
    //设置运动轨迹之后小人feature显示
    createLabelStyle(personImg) {
      return new Style({
        image: new Icon({
          anchor: [0.5, 0.8], // 居中
          // anchorOrigin: 'top-right',
          // anchorXUnits: 'fraction',
          // anchorYUnits: 'pixels',
          // offsetOrigin: 'top-right',
          // offset:[0,10],
          scale: 0.8, // 图标缩放比例
          opacit: 1, // 透明度
          src: personImg, // 图标的url
        }),
      });
    },
  },
  beforeCreate() {}, //生命周期 - 创建之前
  //生命周期 - 创建完成(可以访问当前this实例)
  created() {},
  beforeMount() {}, //生命周期 - 挂载之前
  //生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {
    //创建地图
    this.initMap();
    this.getTrack();
  },
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style scoped>
#map {
  width: 1000px;
  height: 800px;
  border: 1px solid #333;
  margin: 0 auto;
}
button {
  display: block;
  margin: 10px auto;
}
</style>

你可能感兴趣的:(工作栏目,webgl,vue.js,javascript)