<template>
<div class="map-warp">
<h3>
<a
href="https://openlayers.org/en/latest/examples/feature-move-animation.html?q=polyline"
target="_bank"
>OpenlayersTrack</a>
<!--js 轨迹回放 https://blog.csdn.net/Himire/article/details/80296738 -->
</h3>
<div class="progress-bar">
<div class="bar-box">
<div class="bar" :style="{width:progress+'%'}">
<span>{{progress}}%</span>
</div>
</div>
</div>
<div id="map" class="map"></div>
<el-row :gutter="20">
<el-col :span="5">
<label for="speed">
运动速度:
<input id="speed" type="range" step="10" value="5" />
</label>
</el-col>
<el-col :span="5">
<button @click="handlerPlay">{{textContent}}</button>
</el-col>
</el-row>
</div>
</template>
<script>
import "ol/ol.css";
import Feature from "ol/Feature";
import Map from "ol/Map";
import View from "ol/View";
import Polyline from "ol/format/Polyline";
import { Projection } from "ol/proj";
import { Point, LineString } from "ol/geom";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import XYZ from "ol/source/XYZ";
import VectorSource from "ol/source/Vector";
import {
Circle as CircleStyle,
Fill,
Icon,
Stroke,
Style,
Text
} from "ol/style";
import { getVectorContext } from "ol/render";
export default {
data() {
return {
map: null,
progress: 0,
animating: false,
speed: null,
now: null,
textContent: "开始",
routeCoords: null,
routeLength: null,
route: null,
routeFeature: null,
geoMarker: null,
startMarker: null,
endMarker: null,
styles: {
route: new Style({
stroke: new Stroke({
width: 6,
color: [237, 212, 0, 0.8]
})
}),
icon: new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({ color: "red" }),
stroke: new Stroke({
color: "white",
width: 2
})
})
}),
geoMarker: new Style({
image: new Icon({
anchor: [0.5, 1],
src: require("@/assets/tx-icon-1.png")
})
}),
start: new Style({
image: new Icon({
anchor: [0.5, 1],
src: require("@/assets/rise.png")
})
}),
end: new Style({
image: new Icon({
anchor: [0.5, 1],
src: require("@/assets/end.png")
})
})
},
vectorLayer: null,
center: [118.835014569433, 32.08414190192472]
};
},
methods: {
initMap() {
let that = this;
that.routeCoords = [
[118.83476768752418, 32.08385299388422],
[118.83491813875425, 32.08394894013734],
[118.83504349233812, 32.08408332210981],
[118.83504349233812, 32.08408332210981],
[118.83512889261571, 32.083918456790876],
[118.83517286002402, 32.083733744293006],
[118.83496824937895, 32.084077663081935],
[118.83490797978696, 32.08412326115879],
[118.83489815812887, 32.08414025948315],
[118.83488806541473, 32.084153465524956],
[118.83488315718186, 32.08415572622981],
[118.8348782482698, 32.0841596143537],
[118.83485807031045, 32.08416812475921],
[118.83484798473395, 32.08416424284437],
[118.83483789451235, 32.08417148163059],
[118.83483789122208, 32.08417934749756],
[118.83489794089253, 32.084006273376524],
[118.83490803262733, 32.08399523720106],
[118.83491321591835, 32.08398700421235],
[118.83491812613363, 32.083979861216235],
[118.83491812890527, 32.08397308027895],
[118.83492822118053, 32.0839606878946],
[118.83493831179283, 32.08395236406387],
[118.8349443113023, 32.08394818448314],
[118.83494840317711, 32.0839421415609],
[118.8349582198328, 32.08393707761024],
[118.83495822192893, 32.08393192409512],
[118.83495822314188, 32.083928940480945],
[118.83495822600715, 32.08392188830153],
[118.83496831727095, 32.08391193701643],
[118.83496832133952, 32.083901901220244],
[118.83497432325855, 32.083891754391544],
[118.83497841676457, 32.083881642888024],
[118.83498850812316, 32.083871420344074],
[118.8349985986039, 32.08386336769408],
[118.83499860472438, 32.08384817837085],
[118.83500869639813, 32.08383714209293],
[118.83500870130179, 32.083824936382825],
[118.83501279510463, 32.08381401114558],
[118.83501852555108, 32.08380088571361],
[118.83502861687877, 32.08379066312818]
];
that.routeLength = that.routeCoords.length;
that.route = new LineString(that.routeCoords);
that.routeFeature = new Feature({
type: "route",
geometry: that.route
});
that.geoMarker = new Feature({
type: "geoMarker",
geometry: new Point(that.routeCoords[0])
});
that.startMarker = new Feature({
type: "start",
geometry: new Point(that.routeCoords[0])
});
that.endMarker = new Feature({
type: "end",
geometry: new Point(that.routeCoords[that.routeLength - 1])
});
that.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [
that.routeFeature,
that.geoMarker,
that.startMarker,
that.endMarker
]
}),
style: function(feature) {
if (that.animating && feature.get("type") === "geoMarker") {
return null;
}
return that.styles[feature.get("type")];
}
});
this.map = new Map({
target: "map",
layers: [
new TileLayer({
source: new XYZ({
url:
"http://www.google.cn/maps/vt?lyrs=m@189&gl=cn&x={x}&y={y}&z={z}"
}),
projection: "EPSG:3857"
}),
that.vectorLayer
],
view: new View({
projection: new Projection({ code: "EPSG:4326", units: "degrees" }),
center: this.center,
zoom: 19,
minZoom: 2,
maxZoom: 19
})
});
this.mapClick();
},
mapClick() {
let that = this;
this.map.on("click", function(event) {
let feature = that.map.getFeaturesAtPixel(event.pixel);
let pixel = that.map.getEventPixel(event.originalEvent);
let coodinate = event.coordinate;
if (feature.length > 0) {
console.warn(feature[0].values_.type, 111);
}
});
},
handlerPlay() {
if (this.textContent === "暂停") {
this.stop(false);
} else {
this.start();
}
},
moveFeature(event) {
let vectorContext = getVectorContext(event);
let frameState = event.frameState;
if (this.animating) {
let elapsedTime = frameState.time - this.now;
let index = Math.round((this.speed * elapsedTime) / 1000);
this.progress = Math.floor(
((100 / this.routeLength) * (this.speed * elapsedTime)) / 1000
);
if (index >= this.routeLength) {
this.progress = "100";
this.stop(true);
return;
}
let currentPoint = new Point(this.routeCoords[index]);
let feature = new Feature(currentPoint);
vectorContext.drawFeature(feature, this.styles.geoMarker);
}
this.map.render();
},
start() {
if (this.animating) {
this.stop(false);
} else {
this.animating = true;
this.textContent = "暂停";
this.now = new Date().getTime();
let speedInput = document.getElementById("speed");
this.speed = speedInput.value;
this.geoMarker.setStyle(null);
this.map.getView().setCenter(this.center);
this.vectorLayer.on("postrender", this.moveFeature);
this.map.render();
}
},
stop(ended) {
this.progress = 0;
this.animating = false;
this.textContent = "开始";
let coord = ended
? this.routeCoords[this.routeLength - 1]
: this.routeCoords[0];
let geometry = this.geoMarker.getGeometry().setCoordinates(coord);
this.vectorLayer.un("postrender", this.moveFeature);
}
},
mounted() {
this.initMap();
}
};
</script>
<style lang="scss">
#map {
height: 500px;
margin-top: 20px;
}
.ol-attribution,
.ol-zoom {
display: none;
}
.progress-bar {
width: 100%;
height: 30px;
margin: 30px 0;
background: url("~@/assets/bg-5.png") center bottom no-repeat;
background-size: 100% 30px;
position: relative;
box-sizing: border-box;
.bar-box {
position: absolute;
top: 10px;
left: 30px;
right: 30px;
height: 10px;
border-radius: 5px;
background: #034c77;
}
.bar {
height: 10px;
border-radius: 5px;
background: url("~@/assets/bg-6.png") 0 bottom repeat #ecc520;
position: relative;
span {
width: 50px;
height: 50px;
line-height: 18px;
font-size: 12px;
font-weight: bold;
text-align: center;
position: absolute;
color: #fe0000;
top: -30px;
right: -25px;
background: url("~@/assets/bg-7.png") center 0 no-repeat;
background-size: 100% 30px;
}
}
}
</style>