openlayer的飞行动画

飞行动画官方例子:https://openlayers.org/en/latest/examples/flight-animation.html
openlayer的飞行动画_第1张图片

<template>
  <div class="con-box">
    <div id="map" class="map" />
  </div>
</template>

<script>
import "ol/ol.css";
import olMap from "ol/Map";
import olView from "ol/View";
import ollayerTile from "ol/layer/Tile";
// import olsourceOSM from "ol/source/OSM";
import { get as getProjection, Projection, fromLonLat } from "ol/proj";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Point, LineString, MultiLineString, Polygon } from "ol/geom";
import XYZ from "ol/source/XYZ";
import { Map, View, Feature, ol } from "ol";
import {
  Circle,
  Fill,
  Stroke,
  Style,
  Text,
  Icon,
  Circle as CircleStyle,
} from "ol/style.js";
import Overlay from "ol/Overlay.js";
import { Image } from "ol/layer.js";
import { OSM, Vector, ImageStatic } from "ol/source";
import { defaults as defaultControls } from "ol/control";
import GeoJSON from "ol/format/GeoJSON.js";
import { Tile as TileLayer } from "ol/layer.js";
import Draw, { createBox, createRegularPolygon } from "ol/interaction/Draw";
import { unByKey } from "ol/Observable";
import { getVectorContext } from "ol/render";
import { easeIn, easeOut } from "ol/easing";
import Stamen from "ol/source/Stamen.js";
import {getWidth} from 'ol/extent.js';
const pointsPerMs = 0.02;
export default {
  data() {
    return {
      value: "",
      dataURL1: "https://scpic.chinaz.net/files/pic/pic9/202012/bpic22030.jpg",
      map: null,
      view: null,
      positionLayer: null,
      featuresArr: [],

      opt: {
        img: "",
        imgsize: "",
      },
      geo: null,
      vlayer: null,
      draw: null,
      source: null,
      multiSource: null,
      feature: null,
      duration: 3000,
      tileLayer: null,
      testArr: [],
      simplyArr: [
        [0, 0],
        [-600, 600],
        [600, 0],
        [0, -600],
      ],
      multiArr: [
        [
          [0, 0],
          [600, 600],
          [-600, 0],
          [0, -600],
        ],
        [
          [300, 0],
          [800, 200],
          [0, 0],
          [0, -100],
        ],
      ],
      trackPoint: null,
      simpLine: null,
      multiLine: null,
      traceCroods: null,
      sliderPos: 0,
      styleOl: new Style({
        stroke: new Stroke({
          color: "#EAE911",
          width: 2,
        }),
      }),
      flightsSource: null,
      flightsLayer: null,
    };
  },
  mounted() {
    this.initmap();
  },

  methods: {
    initmap() {
      this.tileLayer = new TileLayer({
        source: new Stamen({
          layer: "toner",
        }),
      });
      this.map = new Map({
        layers: [this.tileLayer],
        target: "map",
        view: new View({
          center: [-11000000, 4600000],
          zoom: 2,
        }),
      });
      this.initFlightMap()
    },
    initFlightMap() {
      let self = this;
      this.flightsSource = new VectorSource({
        attributions:
          "Flight data by " +
          'OpenFlights,',
        loader: function () {
          const url = "data/geojson/flight.json";
          fetch(url)
            .then((response) => {
              return response.json();
            })
            .then((json) => {
              const flightsData = json.flights;
              for (let i = 0; i < flightsData.length; i++) {
                const flight = flightsData[i];
                const from = flight[0];
                const to = flight[1];

                // create an arc circle between the two locations
                const arcGenerator = new arc.GreatCircle(
                  { x: from[1], y: from[0] },
                  { x: to[1], y: to[0] }
                );

                const arcLine = arcGenerator.Arc(100, { offset: 10 });
                // paths which cross the -180°/+180° meridian are split
                // into two sections which will be animated sequentially
                const features = [];
                arcLine.geometries.forEach(function (geometry) {
                  
                  const line = new LineString(geometry.coords);
                  line.transform("EPSG:4326", "EPSG:3857");
                  features.push(
                    new Feature({
                      geometry: line,
                      finished: false,
                    })
                  );
                });
                self.addLater(features, i * 50);
              }
              self.tileLayer.on("postrender", self.animateFlights);
            });
        },
      });
this.flightsLayer = new VectorLayer({
  source: this.flightsSource,
  style: function (feature) {
    // if the animation is still active for a feature, do not
    // render the feature with the layer style
    if (feature.get('finished')) {
      return self.styleOl;
    }
    return null;
  },
});
this.map.addLayer(this.flightsLayer)

    },
    addLater(features, timeout) {
      
      let self=this;
      window.setTimeout(function () {
        let start = Date.now();
        features.forEach(function (feature) {
          feature.set("start", start);
          self.flightsSource.addFeature(feature);
          const duration =
            (feature.getGeometry().getCoordinates().length - 1) / pointsPerMs;
       
          start += duration;
             
        });
      }, timeout);
    },

    animateFlights(event) {
      console.log('渲染事件',event)
      const vectorContext = getVectorContext(event);
      const frameState = event.frameState;
      vectorContext.setStyle(this.styleOl);

      const features = this.flightsSource.getFeatures();
      for (let i = 0; i < features.length; i++) {
        const feature = features[i];
        if (!feature.get("finished")) {
          // only draw the lines for which the animation has not finished yet
          const coords = feature.getGeometry().getCoordinates();
          const elapsedTime = frameState.time - feature.get("start");
          if (elapsedTime >= 0) {
            const elapsedPoints = elapsedTime * pointsPerMs;

            if (elapsedPoints >= coords.length) {
              feature.set("finished", true);
            }

            const maxIndex = Math.min(elapsedPoints, coords.length);
            const currentLine = new LineString(coords.slice(0, maxIndex));

            // animation is needed in the current and nearest adjacent wrapped world
            const worldWidth = getWidth(
              this.map.getView().getProjection().getExtent()
            );
            const offset = Math.floor(
              this.map.getView().getCenter()[0] / worldWidth
            );

            // directly draw the lines with the vector context
            currentLine.translate(offset * worldWidth, 0);
            vectorContext.drawGeometry(currentLine);
            currentLine.translate(worldWidth, 0);
            vectorContext.drawGeometry(currentLine);
          }
        }
      }
      // tell OpenLayers to continue the animation
      this.map.render();
    },


  },
};
</script>

<style scoped>
#map {
  width: 97%;
  margin: 0 auto;
  /* background: rgb(238, 238, 238); */
}

.con-box {
  width: 100%;
  height: 100%;
  border: 1px solid #999999;
}

.map {
  height: 700px;
  border: 1px solid;
}

.icon_but {
  margin: 0 10px;
  padding: 10px;
  border: 1px solid red;
}

.toolbar {
  margin: 10px;
}

.toolbar span {
  display: inline-block;
}

.ol-popup {
  border: 1px solid red;
  font-size: 20px;
  font-weight: bolder;
}

.con-box {
  width: 100%;
  height: calc(100% - 84px);
  border: 1px solid #999999;
}
</style>

你可能感兴趣的:(vue.js,前端)