openlayers8 实现轨迹回放

<template>
	<div>
		<h2 class="h-title">轨迹回放</h2>
		<div id="map" class="map-x"></div>
	</div>
</template>
<script>
import 'ol/ol.css';
import { Feature, Map, View } from 'ol';
import { Tile as TileLayer } from 'ol/layer';
import XYZ from 'ol/source/XYZ';
import { fromLonLat, transform } from 'ol/proj';
import VectorLayer from 'ol/layer/Vector';
import { Vector as VectorSource } from 'ol/source';
import { LineString, MultiPolygon } from 'ol/geom';
import Point from 'ol/geom/Point.js';
import { Style, Circle as CircleStyle, Icon, Fill, RegularShape, Stroke, Text } from 'ol/style';
export default {
	data() {
		return {
			map: null,
			styles: {
				route: new Style({
					stroke: new Stroke({
						color: '#bfa',
						width: 2
					})
				}),
				goMark: new Style({
					image: new CircleStyle({
						radius: 7,
						// snapToPixel: false,
						fill: new Fill({ color: 'black' }),
						stroke: new Stroke({
							color: 'white',
							width: 2
						})
					})
				}),
				startMarker: new Style({
					image: new Icon({
						anchor: [0.5, 1],
						src: require('@/assets/joystick_flat.png'),
						scale: 0.2
					})
				}),
				endMarker: new Style({
					image: new Icon({
						anchor: [0.5, 1],
						src: require('@/assets/joystick_flat.png'),
						scale: 0.2,
						offset: [-10, -35]
					})
				})
			},
			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]
			],
			carPoint: {}
		};
	},
	mounted() {
		this.initMap();
        this.addPointAndView()
	},
	methods: {
		initMap() {
			this.map = new Map({
				target: 'map',
				view: new View({
					center: fromLonLat([120.9800615193, 29.1326618704]),
					zoom: 14
				}),
				layers: [
					new TileLayer({
						source: new XYZ({
							//黑色底图
							url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
						}),
						visible: true
					})
				]
			});
		},
		async addPointAndView() {
			//画轨迹线
			await this.drawLine();
			//开始动
			this.moveStart();
		},
		//轨迹线  把每个点连起来
		drawLine() {
			let line = new Feature({
				geometry: new LineString(this.coordinates)
			});
			let source = new VectorSource({
				features: [line]
			});
			let lineLayer = new VectorLayer({
				source: source
			});
			this.map.addLayer(lineLayer);
		},
		//创建小车这个要素
		moveStart() {
			//坐标转换 方便计算下一个位置
			this.dotsData = this.coordinates.map((item) => {
				return transform(item, 'EPSG:3857', 'EPSG:4326');
			});
			//深复制车的位置,不在原数组改变,方便重新播放
			this.carPoints = [...this.dotsData];
            // 当前的小车
			this.carPoint = new Feature({
				geometry: new Point(fromLonLat(this.carPoints[0]))
			});
            // 设置小车样式
			this.carPoint.setStyle(
				new Style({
					image: new Icon({
						src: require('@/assets/car.png'),
						scale: 0.2,
						anchor: [0.5, 0.5],
						rotation: -this.countRotate()
					})
				})
			);
			let source = new VectorSource({
				features: [this.carPoint]
			});
			this.carLayer = new VectorLayer({
				source: source
			});
			this.map.addLayer(this.carLayer);
			this.timeStart();
		},
		//计时器开始
		timeStart() {
			this.timer = setInterval(() => {
				if (this.routeIndex + 1 >= this.carPoints.length) {
					//重头开始
					this.routeIndex = 0;
					//移除要素
					this.carLayer.getSource().removeFeature(this.carPoint);
					clearInterval(this.timer);
					//重复运动
					this.addPointAndView(); //自动开启功能
					return;
				}
				// 到达下一个点了 需要变化角度
				if (this.nextPoint() === this.carPoints[this.routeIndex + 1]) {
					this.routeIndex++;
					this.carPoint.getStyle().getImage().setRotation(-this.countRotate());
				}
				//改变坐标点
				this.carPoint
					.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];
			// console.log(Math.atan2(p2[0] - p1[0], p2[1] - p1[1]),p2[0] - p1[0],p2[1] - p1[1])
			return Math.atan2(p2[1] - p1[1], p2[0] - p1[0]);
		}
	}
};
</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue是一种流行的JavaScript框架,用于构建用户界面。OpenLayers是一个开源的JavaScript库,用于在web浏览器中显示交互式地图。结合Vue和OpenLayers,我们可以实现台风轨迹的可视化。 首先,我们需要获取台风的相关数据。可以从台风数据的API或其他数据源中获取实时或历史台风数据。数据通常包含台风的经纬度坐标和其他相关信息,如风力、风速等。 在Vue组件中,我们可以使用OpenLayers来显示地图。首先,在Vue组件中引入OpenLayers库,并在Vue的生命周期钩子中初始化地图。可以使用OpenLayers的地图视图类(MapView)来设置地图的中心坐标和缩放级别。 接下来,我们需要将台风的轨迹数据添加到地图上。可以使用OpenLayers的矢量图层(Vector Layer)来添加台风轨迹。将每个台风点的经纬度坐标转OpenLayers的几何对象,并将其添加到矢量图层中。 为了使台风轨迹更具交互性,可以在每个台风点上添加弹出窗口,显示该点的详细信息。可以使用OpenLayers的弹出窗口类(Overlay)和交互类(Interaction)来实现这一功能。 最后,根据需求,可以添加其他地图元素,如底图切、比例尺、图例等,以增强用户体验。 总之,使用Vue和OpenLayers,我们可以方便地将台风轨迹可视化,并提供交互功能。这种方式可以帮助用户更直观地了解台风的路径和特征,从而提高对台风的认知和应对能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值