Uniapp小程序地图轨迹绘画

3,306 阅读2分钟

轨迹绘画

简介

  • 轨迹绘画常用于展示车辆历史轨迹,运动历史记录等,本次案例采用的是汽车案例同时利用腾讯地图API,来实现地图轨迹绘画功能,具体情况根据实际项目变更。

本例是汽车轨迹绘画功能

t7mcx-hlyjp.gif

1.在页面的onReady生命周期中创建map对象

onReady() {
        // 创建map对象
        this.map = uni.createMapContext('map');
        // 获取屏幕高度(此处获取屏幕高度是因为本示例中使用了colorui的cu-custom自定义头部,需根据系统高度来自适应)
        uni.getSystemInfo({
                success: res => {
                        this.windowHeight = res.windowHeight;
                }
        });
},

2.设置轨迹动画事件

页面代码:

<view class="container">
        <map id='map' :latitude="latitude" :longitude="longitude" :markers="covers"
                :style="{ width: '100%', height: mapHeight + 'px' }" :scale="13" :polyline="polyline">
        </map>

        <view class="btnBox">
                <button :disabled="isDisabled" @click="start" class="cu-btn bg-blue round shadow lg">开始回放</button>
                <button @click="pause" class="cu-btn bg-red round shadow lg">暂停</button>
        </view>
</view>

逻辑代码:

  • 1.轨迹动画的开始事件
start() {
        if (this.movementInterval) {
                clearInterval(this.movementInterval);
        }
        this.isStart = true;
        this.moveMarker();
},
  • 2.轨迹动画的暂停事件
pause() {
        this.isStart = false;
        this.isDisabled = false;
        if (this.movementInterval) {
                clearInterval(this.movementInterval);
                this.movementInterval = null;
        }
},
  • 3.轨迹动画移动事件
moveMarker() {
        if (!this.isStart) return;

        if (this.playIndex >= this.coordinate.length) {
                this.playIndex = 0;
                uni.showToast({
                        title: "播放完成",
                        duration: 1400,
                        icon: "none",
                });
                this.isStart = false;
                this.isDisabled = false;
                return;
        }

        let datai = this.coordinate[this.playIndex];
        this.map.translateMarker({
                markerId: 1,
                autoRotate: true,
                destination: {
                        longitude: datai.longitude,
                        latitude: datai.latitude,
                },
                duration: 700,
                complete: () => {
                        this.playIndex++;
                        this.moveMarker();
                },
        });
},

完整代码如下

<!-- 地图轨迹组件 -->
<template>
	<view>
		<cu-custom class="navBox" bgColor="bg-gradual-blue" :isBack="true">
			<block slot="backText">返回</block>
			<block slot="content">地图轨迹</block>
		</cu-custom>

		<view class="container">
			<map id='map' :latitude="latitude" :longitude="longitude" :markers="covers"
				:style="{ width: '100%', height: mapHeight + 'px' }" :scale="13" :polyline="polyline">
			</map>

			<view class="btnBox">
				<button :disabled="isDisabled" @click="start" class="cu-btn bg-blue round shadow lg">开始回放</button>
				<button @click="pause" class="cu-btn bg-red round shadow lg">暂停</button>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				map: null,
				movementInterval: null, // 用于存储定时器的引用
				windowHeight: 0,
				mapHeight: 0,
				timer: null,

				isDisabled: false,
				isStart: false,
				playIndex: 1,

				id: 0, // 使用 marker点击事件 需要填写id
				title: 'map',
				latitude: 34.263734,
				longitude: 108.934843,
				// 标记点
				covers: [{
					id: 1,
					width: 42,
					height: 47,
					rotate: 270,
					latitude: 34.259428,
					longitude: 108.947040,
					iconPath: 'http://zgonline.top/car.png',
					callout: {
						content: "鄂A·88888", // <img src="车牌信息" alt="" width="50%" />
						display: "ALWAYS",
						fontWeight: "bold",
						color: "#5A7BEE", //文本颜色
						fontSize: "12px",
						bgColor: "#ffffff", //背景色
						padding: 5, //文本边缘留白
						textAlign: "center",
					},
					anchor: {
						x: 0.5,
						y: 0.5,
					},
				}],

				// 线
				polyline: [],

				// 坐标数据
				coordinate: [{
						latitude: 34.259428,
						longitude: 108.947040,
						problem: false,
					},
					{
						latitude: 34.252918,
						longitude: 108.946963,
						problem: false,
					},
					{
						latitude: 34.252408,
						longitude: 108.946240,
						problem: false,
					},
					{
						latitude: 34.249286,
						longitude: 108.946184,
						problem: false,
					},
					{
						latitude: 34.248670,
						longitude: 108.946640,
						problem: false,
					},
					{
						latitude: 34.248129,
						longitude: 108.946826,
						problem: false,
					},
					{
						latitude: 34.243537,
						longitude: 108.946816,
						problem: true,
					},
					{
						latitude: 34.243478,
						longitude: 108.939003,
						problem: true,
					},
					{
						latitude: 34.241218,
						longitude: 108.939027,
						problem: true,
					},
					{
						latitude: 34.241192,
						longitude: 108.934802,
						problem: true,
					},
					{
						latitude: 34.241182,
						longitude: 108.932235,
						problem: true,
					},
					{
						latitude: 34.247227,
						longitude: 108.932311,
						problem: true,
					},
					{
						latitude: 34.250833,
						longitude: 108.932352,
						problem: true,
					},
					{
						latitude: 34.250877,
						longitude: 108.931756,
						problem: true,
					},
					{
						latitude: 34.250944,
						longitude: 108.931576,
						problem: true,
					},
					{
						latitude: 34.250834,
						longitude: 108.929662,
						problem: true,
					},
					{
						latitude: 34.250924,
						longitude: 108.926015,
						problem: true,
					},
					{
						latitude: 34.250802,
						longitude: 108.910121,
						problem: true,
					},
					{
						latitude: 34.269718,
						longitude: 108.909921,
						problem: true,
					},
					{
						latitude: 34.269221,
						longitude: 108.922366,
						problem: false,
					},
					{
						latitude: 34.274531,
						longitude: 108.922388,
						problem: false,
					},
					{
						latitude: 34.276201,
						longitude: 108.923433,
						problem: false,
					},
					{
						latitude: 34.276559,
						longitude: 108.924004,
						problem: false,
					},
					{
						latitude: 34.276785,
						longitude: 108.945855,
						problem: false,
					}
				],
				posi: {
					id: 1,
					width: 32,
					height: 32,
					latitude: 0,
					longitude: 0,
					iconPath: "http://cdn.zhoukaiwen.com/car.png",
					callout: {
						content: "鄂A·888888", // 车牌信息
						display: "BYCLICK",
						fontWeight: "bold",
						color: "#5A7BEE", //文本颜色
						fontSize: "12px",
						bgColor: "#ffffff", //背景色
						padding: 5, //文本边缘留白
						textAlign: "center",
					},
					anchor: {
						x: 0.5,
						y: 0.5,
					},
				}
			}
		},
		watch: {},
		// 分享小程序
		onShareAppMessage(res) {
			return {
				title: '看看这个小程序多好玩~',
			};
		},
		onReady() {
			// 创建map对象
			this.map = uni.createMapContext('map');
			// 获取屏幕高度
			uni.getSystemInfo({
				success: res => {
					this.windowHeight = res.windowHeight;
				}
			});
		},
		mounted() {
			this.setNavTop('.navBox')

			this.polyline = [{
				points: this.coordinate,
				color: '#025ADD',
				width: 4,
				dottedLine: false,
			}];
		},
		methods: {
			setNavTop(style) {
				let view = uni.createSelectorQuery().select(style);
				view
					.boundingClientRect((data) => {
						console.log("tabInList基本信息 = " + data.height);
						this.mapHeight = this.windowHeight - data.height;
						console.log(this.mapHeight);
					})
					.exec();
			},
			start() {
				if (this.movementInterval) {
					clearInterval(this.movementInterval);
				}
				this.isStart = true;
				this.moveMarker();
			},
			moveMarker() {
				if (!this.isStart) return;

				if (this.playIndex >= this.coordinate.length) {
					this.playIndex = 0;
					uni.showToast({
						title: "播放完成",
						duration: 1400,
						icon: "none",
					});
					this.isStart = false;
					this.isDisabled = false;
					return;
				}

				let datai = this.coordinate[this.playIndex];
				this.map.translateMarker({
					markerId: 1,
					autoRotate: true,
					destination: {
						longitude: datai.longitude,
						latitude: datai.latitude,
					},
					duration: 700,
					complete: () => {
						this.playIndex++;
						this.moveMarker();
					},
				});
			},
			pause() {
				this.isStart = false;
				this.isDisabled = false;
				if (this.movementInterval) {
					clearInterval(this.movementInterval);
					this.movementInterval = null;
				}
			},
		}
	}
</script>

<style lang="scss" scoped>
	.container {
		position: relative;
	}

	.btnBox {
		width: 750rpx;
		position: absolute;
		bottom: 60rpx;
		z-index: 99;
		display: flex;
		justify-content: space-around;
	}
</style>