赞
踩
- <template>
- <div>
- <div id="map" ref="map" style="width: 100vw; height: 100vh"></div>
- </div>
- </template>
-
- <script>
- import VectorLayer from "ol/layer/Vector";
- import VectorSource from "ol/source/Vector";
- import Feature from "ol/Feature";
- import { Draw } from "ol/interaction";
- import { Style, Fill, Stroke, Circle, Icon } from "ol/style";
- import { transform, fromLonLat, toLonLat } from "ol/proj";
- import { Point, LineString } from "ol/geom";
-
- import { Map, View, interaction, events } from "ol";
- import TileLayer from "ol/layer/Tile";
- import { defaults as defaultControls } from "ol/control";
- import XYZ from "ol/source/XYZ";
-
- export default {
- data() {
- return {
- map: {},
- featureMove: {},
- carPoints: [], //车还要走的点
- routeIndex: 0, //当前小车所在的路段
- timer: {},
- coordinates: [
- [10836932.628965743, 4998172.218425438],
- [10638182.82599503, 3781582.515392581],
- [10897159.841987172, 3552719.105911153],
- [11120000.530166456, 4986126.775821152],
- [11360909.382252172, 4895785.956289009],
- [11053750.595842887, 3420219.23726401],
- [11294659.4479286, 3257605.7621061527],
- [11565681.906525029, 4823513.300663294],
- [11866817.971632171, 4757263.366339724],
- [11535568.300014313, 3185333.1064804387],
- [11812613.479912885, 3058855.959135439],
- [12125794.987624314, 4721127.038526867],
- [12402840.167522885, 4684990.710714009],
- [12023408.725487886, 2926356.090488296],
- [12300453.905386457, 2860106.1561647244],
- [12643749.0196086, 4630786.218994724],
- [12866589.707787886, 4510331.792951867],
- [12547385.478774315, 2878174.3200711533],
- [12932839.642111458, 2878174.3200711533],
- [13113521.281175744, 3751468.908881867],
- [13125566.723780029, 4739195.202433295],
- [13691702.526181456, 5425785.43087758],
- [13553179.936232172, 6112375.659321865],
- [12920794.199507171, 5407717.266971151],
- [12065567.774602886, 4974081.3332168665],
- [12788294.330860028, 4895785.956289009],
- ],
- routeLayer: {},
- };
- },
- mounted() {
- this.initMap(); //初始化地图方法
- this.open(); //自动开启功能
- },
- methods: {
- //初始化地图
- initMap() {
- this.map = new Map({
- target: "map",
- layers: [
- new TileLayer({
- source: new XYZ({
- url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
- }),
- }),
- ],
- view: new View({
- center: fromLonLat([108.522097, 37.272848]),
- zoom: 4.7,
- }),
- });
- },
- //添加矢量图层
- async open() {
- //画轨迹线
- await this.drawLine();
- //开始动
- this.moveStart();
- },
- //轨迹线 把每个点连起来
- drawLine() {
- this.routeLayer = new VectorLayer({
- source: new VectorSource({
- features: [],
- }),
- });
- this.map.addLayer(this.routeLayer);
-
- let comDots = [];
- let wireFeature = {};
- this.coordinates.forEach((item) => {
- comDots.push(item);
- wireFeature = new Feature({
- geometry: new LineString(comDots),
- });
- wireFeature.setStyle(
- new Style({
- stroke: new Stroke({
- // 设置边的样式
- color: "rgb(21, 106, 158)",
- width: 3,
- }),
- })
- );
- this.routeLayer.getSource().addFeatures([wireFeature]);
- });
- },
- //创建小车这个要素
- moveStart() {
- //坐标转换
- this.dotsData = this.coordinates.map((item) => {
- return transform(item, "EPSG:3857", "EPSG:4326");
- });
- //深复制车的位置,不在原数组改变,方便重新播放
- // this.carPoints = JSON.parse(JSON.stringify(this.dotsData));
- this.carPoints = [...this.dotsData];
-
- //小车最初位置在第一个坐标点
- this.featureMove = new Feature({
- geometry: new Point(this.carPoints[0]),
- });
- this.featureMove.setStyle(
- new Style({
- image: new Icon({
- src: "https://openlayers.org/en/v4.6.5/examples/data/icon.png",
- scale: 0.85,
- anchor: [0.5, 0.5],
- rotation: this.countRotate(),
- }),
- })
- );
- //添加车辆元素到图层
- this.routeLayer.getSource().addFeature(this.featureMove);
- this.timeStart();
- },
- //计时器开始
- timeStart() {
- this.timer = setInterval(() => {
- if (this.routeIndex + 1 >= this.carPoints.length) {
- //重头开始
- this.routeIndex = 0;
- //移除要素
- this.routeLayer.getSource().removeFeature(this.featureMove);
- clearInterval(this.timer);
- //重复运动
- this.open(); //自动开启功能
- return;
- }
- //到转折点旋转角度
- if (this.nextPoint() === this.carPoints[this.routeIndex + 1]) {
- this.routeIndex++;
- this.featureMove
- .getStyle()
- .getImage()
- .setRotation(this.countRotate());
- }
- //改变坐标点
- this.featureMove
- .getGeometry()
- .setCoordinates(fromLonLat(this.carPoints[this.routeIndex]));
- }, 10);
- },
- //计算下一个点的位置
- //这里的算法是计算了两点之间的点 两点之间的连线可能存在很多个计算出来的点
- nextPoint() {
- let routeIndex = this.routeIndex;
- let p1 = this.map.getPixelFromCoordinate(
- fromLonLat(this.carPoints[routeIndex])
- ); //获取在屏幕的像素位置
- let p2 = this.map.getPixelFromCoordinate(
- fromLonLat(this.carPoints[routeIndex + 1])
- );
- let dx = p2[0] - p1[0];
- let dy = p2[1] - p1[1];
- //打印可见 在没有走到下一个点之前,下一个点是不变的,前一个点以这个点为终点向其靠近
- let distance = Math.sqrt(dx * dx + dy * dy);
- if (distance <= 1) {
- return this.carPoints[routeIndex + 1];
- } else {
- let x = p1[0] + dx / distance;
- let y = p1[1] + dy / distance;
- let coor = transform(
- this.map.getCoordinateFromPixel([x, y]),
- "EPSG:3857",
- "EPSG:4326"
- );
- this.carPoints[routeIndex] = coor; //这里会将前一个点重新赋值 要素利用这个坐标变化进行移动
- return this.carPoints[routeIndex];
- }
- },
- //计算两点之间的角度 算旋转角度
- countRotate() {
- let i = this.routeIndex,
- j = i + 1;
- if (j === this.carPoints.length) {
- i--;
- j--;
- }
- let p1 = this.carPoints[i];
- let p2 = this.carPoints[j];
- return Math.atan2(p2[0] - p1[0], p2[1] - p1[1]);
- },
- },
- };
- </script>
-
- <style lang="scss" scoped>
- </style>
-
- <template>
- <div>
- <div id="map" style="width: 100vw; height: 100vh" />
- <div id="geo-marker" class="css_animation">
- <img :src="myplanImg" />
- </div>
- <div class="measuretip" id="speed"></div>
- </div>
- </template>
- <script>
- import "ol/ol.css";
- import { Map, View, Feature, Overlay } from "ol";
- import { Vector as VectorLayer } from "ol/layer";
- import { OSM, Vector as VectorSource } from "ol/source";
-
- import { Point, LineString } from "ol/geom.js";
-
- import { Icon, Fill, Stroke, Style, Circle } from "ol/style";
-
- import TileLayer from "ol/layer/Tile";
- export default {
- data() {
- return {
- path: [
- [115.62, 14.82],
- [112.79, 14.82],
- [114.6636, 18.2977],
- [111.687, 18.897],
- [110.3014, 15.063],
- ], // 模拟路径
- pathIndex: 0, // 路径点索引
- marker: {}, //移动点
- splitNumber: 200, // 每两个经纬度之间的分割点
- setIntervalTime: 30, // 移动点间隔时间
- myplanImg: "https://openlayers.org/en/v4.6.5/examples/data/icon.png", // 移动点的图片
- helpTooltipElement: {}, // 平台信息div
- helpTooltip: {}, // 平台信息overlay
- sourceFeatures: new VectorSource(),
- lineString: new LineString([]),
- };
- },
- created() {
- this.analysisPath(this.splitNumber);
- },
- mounted() {
- this.initSeamap();
- },
- methods: {
- initSeamap: function () {
- this.pathIndex = this.path.length - 1;
-
- this.map = new Map({
- target: "map",
- view: new View({
- projection: "EPSG:4326",
- center: [109.8, 18.4],
- zoom: 7,
- minZoom: 3, // 限制最大显示
- maxZoom: 14,
- }),
- layers: [
- new TileLayer({
- source: new OSM(),
- }),
- new VectorLayer({
- // 两点之间的连线
- source: new VectorSource({
- features: [
- new Feature({
- geometry: this.lineString,
- }),
- ],
- }),
- style: [
- new Style({
- stroke: new Stroke({
- width: 3,
- color: "rgba(0, 0, 0, 1)",
- lineDash: [0.1, 5],
- }),
- zIndex: 2,
- }),
- ],
- updateWhileAnimating: true,
- }),
- new VectorLayer({
- // 两端点Feature
- source: this.sourceFeatures,
- }),
- ],
- });
- this.marker = new Overlay({
- positioning: "center-center",
- offset: [0, 0],
- element: document.getElementById("geo-marker"),
- stopEvent: false,
- });
- this.map.addOverlay(this.marker);
- let style1 = [
- // 开始结束点样式
- new Style({
- image: new Icon({
- src: "https://openlayers.org/en/v4.6.5/examples/data/icon.png",
- }),
- }),
- ];
- let feature_start = new Feature({
- geometry: new Point(this.path[0]),
- });
- let feature_end = new Feature({
- geometry: new Point(this.path[this.path.length - 1]),
- });
- feature_start.setStyle(style1);
- feature_end.setStyle(style1);
-
- this.sourceFeatures.addFeatures([feature_start, feature_end]);
-
- this.lineString.setCoordinates(this.path);
- this.helpTooltipElement = document.createElement("div");
- this.helpTooltipElement.className = "measuretip";
- this.helpTooltipElement.id = "speed";
- this.helpTooltip = new Overlay({
- element: this.helpTooltipElement,
- offset: [15, 0],
- positioning: "center-left",
- });
- this.map.addOverlay(this.helpTooltip);
- this.map.once("postcompose", (event) => {
- setInterval(() => {
- this.animation();
- }, this.setIntervalTime);
- });
- },
- animation: function () {
- if (this.pathIndex === -1) {
- this.pathIndex = this.path.length - 1;
- }
- this.marker.setPosition(this.path[this.pathIndex]);
- this.helpTooltipElement.innerHTML =
- "<B>名称:</B>船载应急通信系统" +
- "<br>" +
- "<B>子系统:</B>平台A,平台B" +
- "<br>" +
- "<B>经纬度:</B>" +
- (this.path[this.pathIndex][0] + "").substring(0, 6) +
- "," +
- (this.path[this.pathIndex][1] + "").substring(0, 5);
- this.helpTooltip.setPosition(this.path[this.pathIndex]);
- this.pathIndex--;
- },
- analysisPath: function (splitNumber) {
- let tempPath = [...this.path];
-
- let pathResults = [];
- let tempPoint = [0, 0];
- if (tempPath.length > 1) {
- for (let i = 0; i < tempPath.length - 1; i++) {
- // 每两个点之间分割出splitNumber个点
- pathResults.push(tempPath[i]);
- for (let j = 0; j < splitNumber; j++) {
- tempPoint[0] =
- ((tempPath[i + 1][0] - tempPath[i][0]) * (j + 1)) / splitNumber +
- tempPath[i][0];
- tempPoint[1] =
- ((tempPath[i + 1][1] - tempPath[i][1]) * (j + 1)) / splitNumber +
- tempPath[i][1];
- pathResults.push([...tempPoint]);
- }
- }
- pathResults.push(tempPath[tempPath.length - 1]);
- this.path = [...pathResults];
- }
- },
- },
- };
- </script>
-
- <style>
- .measuretip {
- position: relative;
- background-color: #0d9bf2;
- opacity: 0.7;
- border-radius: 3px;
- padding: 10px;
- font-size: 12px;
- cursor: default;
- }
- </style>
-
- <template>
- <div>
- <div id="map" style="width: 100vw; height: 100vh" />
- <div style="position: fixed; top: 200px; left: 200px">
- <el-button @click="startAnimation()">开始</el-button>
- <el-button @click="stopAnimation()">暂停</el-button>
- </div>
- </div>
- </template>
- <script>
- import "ol/ol.css";
- import { Map, View, Feature, Overlay } from "ol";
- import { Vector as VectorLayer } from "ol/layer";
- import { XYZ, OSM, Vector as VectorSource } from "ol/source";
-
- import { Point, LineString } from "ol/geom.js";
-
- import { Icon, Fill, Stroke, Style, Circle } from "ol/style";
-
- import TileLayer from "ol/layer/Tile";
- import { ScaleLine, defaults as defaultControls } from "ol/control";
-
- import { getVectorContext } from "ol/render";
-
- export default {
- data() {
- return {
- map: {},
- route: new LineString([
- [115.62, 14.82],
- [112.79, 14.82],
- [114.6636, 18.2977],
- [111.687, 18.897],
- [110.3014, 15.063],
- ]),
- geometryMove: {},
- featureMove: {},
- styles: {
- route: new Style({
- stroke: new Stroke({
- width: 6,
- color: [237, 212, 0, 0.8],
- }),
- }),
- icon: new Style({
- image: new Icon({
- anchor: [0.5, 1],
- src: "https://openlayers.org/en/v4.6.5/examples/data/icon.png",
- scale: 1, //设置大小
- }),
- }),
- featureMove: new Style({
- image: new Circle({
- radius: 7,
- fill: new Fill({ color: "black" }),
- stroke: new Stroke({
- color: "white",
- width: 2,
- }),
- }),
- }),
- },
- vectorLayer: {},
- distance: 0,
- lastTime: 0,
- speed: 0.1,
- };
- },
- created() {},
- mounted() {
- this.initMap();
- },
- methods: {
- initMap() {
- this.geometryMove = new Point(this.route.getFirstCoordinate());
-
- this.featureMove = new Feature({
- type: "featureMove",
- geometry: this.geometryMove,
- });
- this.vectorLayer = new VectorLayer({
- source: new VectorSource({
- features: [
- new Feature({
- type: "route",
- geometry: this.route,
- }),
- this.featureMove,
- new Feature({
- type: "icon",
- geometry: new Point(this.route.getFirstCoordinate()),
- }),
- new Feature({
- type: "icon",
- geometry: new Point(this.route.getLastCoordinate()),
- }),
- ],
- }),
- style: (feature) => {
- return this.styles[feature.get("type")];
- },
- });
- this.map = new Map({
- target: "map",
- view: new View({
- projection: "EPSG:4326",
- center: [109.8, 18.4],
- zoom: 7,
- }),
- layers: [
- new TileLayer({
- source: new OSM(),
- }),
- ],
- });
- this.map.addLayer(this.vectorLayer);
- },
- moveFeature(e) {
- let time = e.frameState.time;
- this.distance =
- (this.distance + (this.speed * (time - this.lastTime)) / 1000) % 1; //%2表示:起止止起;%1表示:起止起止
-
- this.lastTime = time;
-
- const currentCoordinate = this.route.getCoordinateAt(
- this.distance > 1 ? 2 - this.distance : this.distance
- );
- this.geometryMove.setCoordinates(currentCoordinate);
- const vectorContext = getVectorContext(e);
- vectorContext.setStyle(this.styles.featureMove);
- vectorContext.drawGeometry(this.geometryMove);
- this.map.render();
- },
- startAnimation() {
- this.lastTime = Date.now();
- this.vectorLayer.on("postrender", this.moveFeature);
- this.featureMove.setGeometry(null); //必须用null,不能用{}
- },
-
- stopAnimation() {
- this.featureMove.setGeometry(this.geometryMove);
- this.vectorLayer.un("postrender", this.moveFeature);
- },
- },
- };
- </script>
-
-
使用:
- <template>
- <div>
- <div id="map" style="height: 100vh; width: 100vw"></div>
- <div style="position: fixed; top: 100px; left: 200px">
- <el-button @click="openAnimation()">打开动画</el-button>
- <el-button @click="closeAnimation()">关闭动画</el-button>
- </div>
-
- <LjOlCarRoute
- ref="ref_LjOlCarRoute"
- :map="map"
- :coordinates="coordinates_route"
- :speed="0.1"
- v-if="showAnimation"
- ></LjOlCarRoute>
- </div>
- </template>
-
- <script>
- import "ol/ol.css";
- import { Map, View } from "ol";
- import { OSM } from "ol/source";
- import { Tile as TileLayer } from "ol/layer";
- import LjOlCarRoute from "@/components/LjOlCarRoute/index.vue";
-
- export default {
- components: { LjOlCarRoute },
- data() {
- return {
- map: {},
- showAnimation: false,
- coordinates_route: [
- [104.2979180563, 30.528298024],
- [104.2987389704, 30.527798338],
- [104.2974397847, 30.5265062907],
- [104.296943667091881, 30.52468992916009],
- ],
- };
- },
- created() {},
- mounted() {
- this.initMap();
- },
- computed: {},
- methods: {
- initMap() {
- this.map = new Map({
- target: "map",
- layers: [
- new TileLayer({
- source: new OSM(),
- }),
- ],
- view: new View({
- projection: "EPSG:4326",
- center: [104.2974397847, 30.5265062907],
- zoom: 18,
- }),
- });
- },
- openAnimation() {
- this.showAnimation = true;
- },
- closeAnimation() {
- this.$refs.ref_LjOlCarRoute.removeLayer();
- this.showAnimation = false;
- },
- },
- };
- </script>
组件:LjOlCarRoute/index.vue:
-
- <template>
- <div>
- <div style="position: fixed; top: 200px; left: 200px">
- <el-button @click="startAnimation()">开始</el-button>
- <el-button @click="stopAnimation()">暂停</el-button>
- </div>
- </div>
- </template>
- <script>
- import "ol/ol.css";
- import { Map, View, Feature, Overlay } from "ol";
- import { Vector as VectorLayer } from "ol/layer";
- import { XYZ, OSM, Vector as VectorSource } from "ol/source";
-
- import { Point, LineString } from "ol/geom.js";
-
- import { Icon, Fill, Stroke, Style, Circle } from "ol/style";
-
- import TileLayer from "ol/layer/Tile";
-
- import { getVectorContext } from "ol/render";
-
- export default {
- name: "LjOlCarRoute",
- props: {
- map: {
- type: Object,
- default: () => {},
- required: true,
- },
- coordinates: {
- type: Array,
- default: () => [
- [115.62, 14.82],
- [112.79, 14.82],
- [114.6636, 18.2977],
- [111.687, 18.897],
- [110.3014, 15.063],
- ],
- },
- startPointImage: {
- type: String,
- default:
- "https://smart-garden-manage.oss-cn-chengdu.aliyuncs.com/position.png",
- },
- endPointImage: {
- type: String,
- default:
- "https://smart-garden-manage.oss-cn-chengdu.aliyuncs.com/position.png",
- },
- movePointImage: {
- type: String,
- default:
- "https://smart-garden-manage.oss-cn-chengdu.aliyuncs.com/xiaoche.png",
- },
- speed: {
- type: Number,
- default: 0.1,
- },
- },
- data() {
- return {
- route: new LineString(this.coordinates),
- geometryMove: {},
- featureMove: {},
- styles: {
- route: new Style({
- stroke: new Stroke({
- width: 6,
- color: [237, 212, 0, 0.8],
- }),
- }),
- startIcon: new Style({
- image: new Icon({
- anchor: [0.5, 1],
- src: this.startPointImage,
- scale: 1, //设置大小
- }),
- }),
- endIcon: new Style({
- image: new Icon({
- anchor: [0.5, 1],
- src: this.endPointImage,
- scale: 1, //设置大小
- }),
- }),
- featureMove: new Style({
- image: new Icon({
- // anchor: [0.5, 1],
- src: this.movePointImage,
- scale: 0.2, //设置大小
- }),
- }),
- },
- vectorLayer: {},
- distance: 0,
- lastTime: 0,
- };
- },
- created() {},
- mounted() {
- this.initMap();
- },
- methods: {
- initMap() {
- this.geometryMove = new Point(this.route.getFirstCoordinate());
-
- this.featureMove = new Feature({
- type: "featureMove",
- geometry: this.geometryMove,
- });
- this.vectorLayer = new VectorLayer({
- source: new VectorSource({
- features: [
- new Feature({
- type: "route",
- geometry: this.route,
- }),
- this.featureMove,
- new Feature({
- type: "startIcon",
- geometry: new Point(this.route.getFirstCoordinate()),
- }),
- new Feature({
- type: "endIcon",
- geometry: new Point(this.route.getLastCoordinate()),
- }),
- ],
- }),
- style: (feature) => {
- return this.styles[feature.get("type")];
- },
- });
- this.map.addLayer(this.vectorLayer);
- },
- moveFeature(e) {
- let time = e.frameState.time;
- this.distance =
- (this.distance + (this.speed * (time - this.lastTime)) / 1000) % 1; //%2表示:起止止起;%1表示:起止起止
-
- this.lastTime = time;
-
- const currentCoordinate = this.route.getCoordinateAt(
- this.distance > 1 ? 2 - this.distance : this.distance
- );
- this.geometryMove.setCoordinates(currentCoordinate);
- const vectorContext = getVectorContext(e);
- vectorContext.setStyle(this.styles.featureMove);
- vectorContext.drawGeometry(this.geometryMove);
- this.map.render();
- },
- startAnimation() {
- this.lastTime = Date.now();
- this.vectorLayer.on("postrender", this.moveFeature);
- this.featureMove.setGeometry(null); //必须用null,不能用{}
- },
-
- stopAnimation() {
- this.featureMove.setGeometry(this.geometryMove);
- this.vectorLayer.un("postrender", this.moveFeature);
- },
- removeLayer() {
- this.map.removeLayer(this.vectorLayer);
- this.vectorLayer.getSource().clear();
- this.featureMove = {};
- this.geometryMove = {};
- },
- },
- };
- </script>
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。