最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

uniapp封裝地圖運(yùn)動(dòng)軌跡完整實(shí)例代碼

 更新時(shí)間:2026年05月23日 08:33:56   作者:派大星jason  
隨著移動(dòng)應(yīng)用的普及和定位技術(shù)的迅猛發(fā)展,地圖和定位功能已經(jīng)成為了現(xiàn)代移動(dòng)應(yīng)用中不可缺少的一部分,uniapp是一種基于Vue.js開發(fā)的跨平臺(tái)應(yīng)用開發(fā)框架,可以方便開發(fā)者在多個(gè)平臺(tái)上共用代碼,這篇文章主要介紹了uniapp封裝地圖運(yùn)動(dòng)軌跡的相關(guān)資料,需要的朋友可以參考下

注意:封裝的地圖運(yùn)動(dòng)軌跡只測(cè)試了微信小程序,其他平臺(tái)未測(cè)試

不過實(shí)現(xiàn)功能的核心API就是這幾個(gè):uniapp.dcloud.net.cn/api/locatio…

展示的核心組件是:uniapp.dcloud.net.cn/component/m…

不同平臺(tái)根據(jù)文檔中的差異說明修改代碼即可

實(shí)現(xiàn)的功能:

  • 獲取當(dāng)前位置信息并展示
  • 在前/后臺(tái)實(shí)時(shí)獲取運(yùn)動(dòng)軌跡并渲染
  • 支持暫停/繼續(xù)記錄軌跡

功能效果:

軌跡效果如下圖(由于開發(fā)的時(shí)候不方便肉身移動(dòng),所以就貼一張靜態(tài)的軌跡圖吧)

開始前先在配置文件manifest.json中找到 mp-weixin 的配置項(xiàng),然后加上下面的配置

"permission": {
			"scope.userLocation": {
				"desc": "你的位置信息將用于小程序位置接口的效果展示"
			}
		},
		"requiredPrivateInfos": [
			"getLocation",
			"startLocationUpdate",
			"startLocationUpdateBackground",
			"onLocationChange"
		],
		"requiredBackgroundModes": ["location"],

代碼

<template>
	<view class="container">
		<!-- 地圖容器 -->
		<map
			id="map"
			class="map"
			:latitude="mapCenter.latitude"
			:longitude="mapCenter.longitude"
			:scale="16"
			:markers="markers"
			:polyline="polyline"
			:enable-3D="true"
			:show-compass="false"
			:enable-zoom="true"
			:enable-scroll="true"
			:enable-rotate="true"
			:enable-overlooking="true"
			:enable-satellite="false"
			:enable-traffic="false"
			:show-location="true"
		></map>

		<div class="operate-box" v-if="!isViewMode">
			<!-- 定位模式切換 -->
			<view class="mode-panel" v-if="!isTracking">
				<view class="mode-item">
					<text class="mode-label">定位模式 :</text>
					<view class="mode-switch">
						<text class="mode-text" :class="{ active: !isBackgroundMode }">前臺(tái)定位</text>
						<switch
							:checked="isBackgroundMode"
							:disabled="!isLocationBackgroundAuth"
							@change="toggleBackgroundMode"
							color="#007AFF"
						/>
						<text class="mode-text" :class="{ active: isBackgroundMode }">后臺(tái)定位</text>
					</view>
				</view>
			</view>
			<!-- 控制按鈕 -->
			<view class="control-panel">
				<view class="control-btn" :class="{ active: isTracking }" @click="toggleTracking">
					{{ isTracking ? '結(jié)束記錄' : '開始記錄' }}
				</view>
				<view
					class="control-btn pause-btn"
					:class="{ 'pause-active': isPause }"
					v-if="isTracking"
					@click="togglePause"
				>
					{{ isPause ? '繼續(xù)記錄' : '暫停記錄' }}
				</view>
				<view class="control-btn" v-if="!isTracking && trackPoints.length > 0" @click="saveTrack">
					保存軌跡記錄
				</view>
			</view>
		</div>

		<!-- 運(yùn)動(dòng)信息面板 -->
		<view class="info-panel" v-if="trackPoints.length > 0 || isViewMode">
			<!-- 暫停狀態(tài)提示 -->
			<view class="pause-status" v-if="isPause">
				<text class="pause-text">?? 記錄已暫停</text>
			</view>
			<view class="info-item">
				<text class="info-label">總距離:</text>
				<text class="info-value">{{ !isViewMode ? totalDistance : viewModeTotalDistance }}km</text>
			</view>
			<view class="info-item">
				<text class="info-label">運(yùn)動(dòng)時(shí)長(zhǎng):</text>
				<text class="info-value">{{ !isViewMode ? formatDuration : viewModeFormatDuration }}</text>
			</view>
			<view class="info-item">
				<text class="info-label">平均速度:</text>
				<text class="info-value">{{ !isViewMode ? averageSpeed : viewModeAverageSpeed }}km/h</text>
			</view>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		onMounted,
		computed,
		watchEffect,
		getCurrentInstance,
		onBeforeUnmount,
		nextTick,
	} from 'vue';
	import { onLoad } from '@dcloudio/uni-app';

	const { proxy } = getCurrentInstance();
	const eventChannel = proxy.getOpenerEventChannel();

	import { getSetting } from '@/utils/index';

	onLoad((res) => {
		if (res.viewId) {
			viewId = res.viewId;
			isViewMode.value = true;
			let trackData = uni.getStorageSync('trackData') || [];
			trackData = trackData.find((item) => item.id == viewId);
			if (trackData) {
				mapCenter.value = trackData.mapCenter;
				markers.value = trackData.markers;
				polyline.value = trackData.polyline;
				viewModeTotalDistance.value = trackData.viewModeTotalDistance;
				viewModeFormatDuration.value = trackData.viewModeFormatDuration;
				viewModeAverageSpeed.value = trackData.viewModeAverageSpeed;
			} else {
				uni.showToast({
					title: '軌跡記錄不存在',
					icon: 'none',
				});
			}
			return;
		}

		// 檢查后臺(tái)定位權(quán)限
		getSetting('scope.userLocationBackground', '請(qǐng)?jiān)谠O(shè)置中開啟后臺(tái)定位權(quán)限', () => {
			isLocationBackgroundAuth.value = true;
			isBackgroundMode.value = true;
		});
		// 檢查前臺(tái)定位權(quán)限
		getSetting('scope.userLocation', '請(qǐng)?jiān)谠O(shè)置中開啟地理位置權(quán)限', () => {
			isLocationAuth.value = true;
			getCurrentLocation();
		});
	});

	onBeforeUnmount(() => {
		// 停止位置監(jiān)聽
		stopLocationTracking();
	});

	const isViewMode = ref(false); // 是否是查看模式
	let viewId = ''; // 查看模式下的id
	const viewModeTotalDistance = ref(0); // 查看模式下的總距離
	const viewModeFormatDuration = ref('00:00:00'); // 查看模式下的運(yùn)動(dòng)時(shí)長(zhǎng)
	const viewModeAverageSpeed = ref('0.00'); // 查看模式下的平均速度

	const isLocationAuth = ref(false); // 是否授權(quán)地理位置權(quán)限
	const isLocationBackgroundAuth = ref(false); // 是否授權(quán)后臺(tái)定位權(quán)限

	const isTracking = ref(false); // 是否正在記錄
	const isBackgroundMode = ref(false); // 是否使用后臺(tái)定位模式

	const isPause = ref(false); // 是否暫停記錄
	const isContinueAfterPause = ref(false); // 是否暫停后繼續(xù)記錄
	const pauseNum = ref(0); // 暫停次數(shù)
	const pauseDistance = ref(0); // 暫停距離
	const pauseMarker = ref({}); // 暫停點(diǎn)標(biāo)記

	const trackPoints = ref([]); // 軌跡點(diǎn)
	const markers = ref([]); // 地圖標(biāo)記點(diǎn)
	const polyline = ref([]); // 軌跡線

	// 地圖中心點(diǎn)
	const mapCenter = ref({
		latitude: 39.909,
		longitude: 116.397,
	});

	let timer = null; // 定時(shí)器
	const startTime = ref(null); // 開始時(shí)間
	const currentTime = ref(Date.now()); // 當(dāng)前時(shí)間,用于實(shí)時(shí)更新
	const pauseStartTime = ref(null); // 暫停開始時(shí)間
	const totalPauseTime = ref(0); // 總暫停時(shí)間(毫秒)

	// 計(jì)算兩點(diǎn)間距離(米)
	function calculateDistance(lat1, lng1, lat2, lng2) {
		const R = 6371000; // 地球半徑(米)
		const dLat = ((lat2 - lat1) * Math.PI) / 180;
		const dLng = ((lng2 - lng1) * Math.PI) / 180;
		const a =
			Math.sin(dLat / 2) * Math.sin(dLat / 2) +
			Math.cos((lat1 * Math.PI) / 180) *
				Math.cos((lat2 * Math.PI) / 180) *
				Math.sin(dLng / 2) *
				Math.sin(dLng / 2);
		const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		return R * c;
	}

	// 總距離
	const totalDistance = computed(() => {
		if (trackPoints.value.length < 2) return 0;

		let distance = 0;
		for (let i = 1; i < trackPoints.value.length; i++) {
			distance += calculateDistance(
				trackPoints.value[i - 1].latitude,
				trackPoints.value[i - 1].longitude,
				trackPoints.value[i].latitude,
				trackPoints.value[i].longitude
			);
		}
		distance -= pauseDistance.value;
		return (distance / 1000).toFixed(2);
	});

	// 運(yùn)動(dòng)時(shí)長(zhǎng)
	const formatDuration = computed(() => {
		// 確保所有必要的值都存在且有效
		if (!startTime.value || !currentTime.value) return '00:00:00';

		// 計(jì)算實(shí)際運(yùn)動(dòng)時(shí)長(zhǎng)(排除暫停時(shí)間)
		const actualDuration = currentTime.value - startTime.value - totalPauseTime.value;

		// 防止出現(xiàn)負(fù)數(shù)或異常值
		if (actualDuration < 0) {
			console.log('運(yùn)動(dòng)時(shí)長(zhǎng)計(jì)算異常:', {
				currentTime: currentTime.value,
				startTime: startTime.value,
				totalPauseTime: totalPauseTime.value,
				actualDuration: actualDuration,
			});
			return '00:00:00';
		}

		const hours = Math.floor(actualDuration / 3600000);
		const minutes = Math.floor((actualDuration % 3600000) / 60000);
		const seconds = Math.floor((actualDuration % 60000) / 1000);

		return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds
			.toString()
			.padStart(2, '0')}`;
	});

	// 平均速度
	const averageSpeed = computed(() => {
		if (totalDistance.value <= 0 || !startTime.value) return 0;

		// 使用實(shí)際運(yùn)動(dòng)時(shí)長(zhǎng)計(jì)算平均速度(排除暫停時(shí)間)
		const actualDuration = (currentTime.value - startTime.value - totalPauseTime.value) / 3600000; // 小時(shí)

		// 防止出現(xiàn)負(fù)數(shù)或異常值
		if (actualDuration <= 0) return 0;

		return (totalDistance.value / actualDuration).toFixed(2);
	});

	// 獲取當(dāng)前位置
	function getCurrentLocation() {
		return new Promise((resolve, reject) => {
			uni.getLocation({
				type: 'gcj02',
				success: (res) => {
					mapCenter.value = {
						latitude: res.latitude,
						longitude: res.longitude,
					};
					resolve();
				},
				fail: (err) => {
					console.error('獲取位置失敗:', err);
					reject(err);
				},
			});
		});
	}

	// 添加地圖標(biāo)記點(diǎn)
	function addMarker(data) {
		markers.value.push({
			id: data.id,
			latitude: data.latitude,
			longitude: data.longitude,
			width: 20,
			height: 20,
			callout: {
				content: data.content,
				color: '#ffffff',
				fontSize: 12,
				borderRadius: 4,
				bgColor: '#007AFF',
				padding: 4,
				display: 'ALWAYS',
			},
		});
		console.log('添加標(biāo)記點(diǎn):', data.content, '當(dāng)前標(biāo)記點(diǎn)總數(shù):', markers.value.length);
	}

	// 啟動(dòng)定時(shí)器
	function startTimer() {
		if (timer) return;
		timer = setInterval(() => {
			currentTime.value = Date.now();
		}, 1000); // 每秒更新一次
	}
	// 停止定時(shí)器
	function stopTimer() {
		if (timer) {
			clearInterval(timer);
			timer = null;
		}
	}

	// 暫停/繼續(xù)記錄
	function togglePause() {
		if (isPause.value) {
			// 繼續(xù)記錄
			resumeTracking();
		} else {
			// 暫停記錄
			pauseTracking();
		}
	}

	// 暫停記錄
	async function pauseTracking() {
		console.log('調(diào)用暫停記錄函數(shù),當(dāng)前狀態(tài):', {
			isTracking: isTracking.value,
			isPause: isPause.value,
		});

		isPause.value = true;
		pauseStartTime.value = Date.now();

		// 停止位置監(jiān)聽(但不添加結(jié)束點(diǎn)標(biāo)記)
		uni.stopLocationUpdate({
			success: () => {
				console.log('暫停位置監(jiān)聽成功');
				// 移除位置變化監(jiān)聽
				uni.offLocationChange();
			},
			fail: (err) => {
				console.error('暫停位置監(jiān)聽失敗:', err);
			},
		});

		// 停止定時(shí)器
		stopTimer();

		uni.showToast({
			title: '已暫停記錄',
			icon: 'none',
		});

		isContinueAfterPause.value = true;

		pauseNum.value++;
		await getCurrentLocation();
		addMarker({
			latitude: mapCenter.value.latitude,
			longitude: mapCenter.value.longitude,
			id: new Date().getTime(),
			content: `暫停點(diǎn)${pauseNum.value}`,
		});

		pauseMarker.value = {
			latitude: mapCenter.value.latitude,
			longitude: mapCenter.value.longitude,
		};
	}

	// 繼續(xù)記錄
	async function resumeTracking() {
		console.log('調(diào)用繼續(xù)記錄函數(shù),當(dāng)前狀態(tài):', {
			isTracking: isTracking.value,
			isPause: isPause.value,
		});

		isPause.value = false;

		// 計(jì)算暫停時(shí)間并累加到總暫停時(shí)間
		if (pauseStartTime.value) {
			const pauseDuration = Date.now() - pauseStartTime.value;
			totalPauseTime.value += pauseDuration;
			pauseStartTime.value = null;
			console.log('暫停時(shí)長(zhǎng):', pauseDuration, 'ms, 總暫停時(shí)間:', totalPauseTime.value, 'ms');
		}

		// 立即更新當(dāng)前時(shí)間,避免顯示暫停前的時(shí)間
		currentTime.value = Date.now();

		// 重新開始位置監(jiān)聽(不重新初始化,只恢復(fù)監(jiān)聽)
		resumeLocationTracking();

		// 重新開始定時(shí)器
		startTimer();

		uni.showToast({
			title: '已繼續(xù)記錄',
			icon: 'none',
		});

		await getCurrentLocation();
		addMarker({
			latitude: mapCenter.value.latitude,
			longitude: mapCenter.value.longitude,
			id: new Date().getTime(),
			content: `繼續(xù)點(diǎn)${pauseNum.value}`,
		});
	}

	// 恢復(fù)位置監(jiān)聽(不重新初始化)
	function resumeLocationTracking() {
		// 根據(jù)模式選擇不同的位置監(jiān)聽方式
		const locationConfig = {
			success: () => {
				console.log('恢復(fù)位置監(jiān)聽');
				// 添加位置變化監(jiān)聽
				uni.onLocationChange((res) => {
					handleLocationChange(res);
				});
			},
			fail: (err) => {
				console.error('恢復(fù)位置監(jiān)聽失敗:', err);
				uni.showToast({
					title: '恢復(fù)監(jiān)聽失敗',
					icon: 'none',
				});
			},
		};

		if (isBackgroundMode.value) {
			// 使用后臺(tái)定位
			console.log('恢復(fù)后臺(tái)定位模式');
			uni.startLocationUpdateBackground(locationConfig);
		} else {
			// 使用前臺(tái)定位
			console.log('恢復(fù)前臺(tái)定位模式');
			uni.startLocationUpdate(locationConfig);
		}
	}

	// 開始/停止記錄
	function toggleTracking() {
		console.log('調(diào)用切換記錄函數(shù),當(dāng)前狀態(tài):', {
			isTracking: isTracking.value,
			isPause: isPause.value,
		});

		if (isTracking.value) {
			stopLocationTracking();
		} else {
			startLocationTracking();
		}
	}

	// 切換后臺(tái)定位模式
	function toggleBackgroundMode(e) {
		isBackgroundMode.value = e.detail.value;
		console.log('切換定位模式:', isBackgroundMode.value ? '后臺(tái)定位' : '前臺(tái)定位');
	}

	// 開始位置監(jiān)聽
	function startLocationTracking() {
		console.log('調(diào)用開始位置監(jiān)聽函數(shù),當(dāng)前狀態(tài):', {
			isTracking: isTracking.value,
			isPause: isPause.value,
			trackPointsCount: trackPoints.value.length,
		});

		// 防止重復(fù)調(diào)用
		if (isTracking.value) {
			console.log('已經(jīng)在記錄狀態(tài),跳過重復(fù)調(diào)用');
			return;
		}

		// 如果是重新開始記錄(之前已經(jīng)停止過),重置所有時(shí)間相關(guān)狀態(tài)
		// 判斷條件:有軌跡點(diǎn)且當(dāng)前不在記錄狀態(tài)且不是暫停狀態(tài),說明是重新開始
		if (trackPoints.value.length > 0 && !isTracking.value && !isPause.value) {
			// 重置所有狀態(tài)
			resetState();

			// 延遲一幀確保狀態(tài)更新后再開始監(jiān)聽
			nextTick(() => {
				initLocationTrackingInternal();
			});
			return;
		}

		// 正常開始記錄
		initLocationTrackingInternal();
	}

	// 內(nèi)部初始化位置監(jiān)聽函數(shù)
	async function initLocationTrackingInternal() {
		if (isBackgroundMode.value) {
			// 后臺(tái)定位模式
			if (isLocationAuth.value && isLocationBackgroundAuth.value) {
				initLocationTracking();
			} else {
				if (!isLocationAuth.value) {
					uni.showModal({
						title: '需要地理位置權(quán)限',
						content: '請(qǐng)?jiān)谠O(shè)置中開啟地理位置權(quán)限',
						showCancel: false,
					});
				} else if (!isLocationBackgroundAuth.value) {
					uni.showModal({
						title: '需要后臺(tái)定位權(quán)限',
						content: '請(qǐng)?jiān)谠O(shè)置中開啟后臺(tái)定位權(quán)限',
						showCancel: false,
					});
				}
			}
		} else {
			// 前臺(tái)定位模式
			if (isLocationAuth.value) {
				initLocationTracking();
			} else {
				uni.showModal({
					title: '需要地理位置權(quán)限',
					content: '請(qǐng)?jiān)谠O(shè)置中開啟地理位置權(quán)限',
					showCancel: false,
				});
			}
		}
	}

	// 初始化位置監(jiān)聽
	async function initLocationTracking() {
		// 根據(jù)模式選擇不同的位置監(jiān)聽方式
		const locationConfig = {
			success: async () => {
				console.log('開始監(jiān)聽位置變化');
				isTracking.value = true;

				// 只在第一次開始記錄時(shí)設(shè)置開始時(shí)間
				if (!startTime.value) {
					startTime.value = Date.now();
					console.log('設(shè)置開始時(shí)間:', new Date(startTime.value).toLocaleString());
				}

				startTimer(); // 開始定時(shí)器

				// 添加位置變化監(jiān)聽
				uni.onLocationChange((res) => {
					handleLocationChange(res);
				});

				// 每次開始記錄時(shí)都添加起始點(diǎn)標(biāo)記
				await getCurrentLocation();
				addMarker({
					latitude: mapCenter.value.latitude,
					longitude: mapCenter.value.longitude,
					id: new Date().getTime(),
					content: '起始點(diǎn)',
				});

				uni.showToast({
					title: '已開始記錄',
					icon: 'none',
				});
			},
			fail: (err) => {
				console.error('開始監(jiān)聽位置變化失敗:', err);
				uni.showToast({
					title: '開始監(jiān)聽失敗',
					icon: 'none',
				});
			},
		};

		if (isBackgroundMode.value) {
			// 使用后臺(tái)定位
			console.log('使用后臺(tái)定位模式');
			uni.startLocationUpdateBackground(locationConfig);
		} else {
			// 使用前臺(tái)定位
			console.log('使用前臺(tái)定位模式');
			uni.startLocationUpdate(locationConfig);
		}
	}

	// 處理位置變化
	function handleLocationChange(location) {
		console.log('位置變化', location);

		// 添加軌跡點(diǎn)
		const point = {
			latitude: location.latitude,
			longitude: location.longitude,
			timestamp: Date.now(),
		};

		if (checkLocation(point)) {
			trackPoints.value.push(point);

			// 更新軌跡線
			updatePolyline();
		}

		// 更新地圖中心點(diǎn)(跟隨用戶位置)
		mapCenter.value = {
			latitude: location.latitude,
			longitude: location.longitude,
		};
	}

	// 校驗(yàn)返回的經(jīng)緯度是否合法:和上一個(gè)經(jīng)緯度相差不能超過100米
	function checkLocation(location) {
		if (trackPoints.value.length === 0) return true;
		const lastPoint = trackPoints.value[trackPoints.value.length - 1];
		const distance = calculateDistance(
			lastPoint.latitude,
			lastPoint.longitude,
			location.latitude,
			location.longitude
		);
		console.log('距離上次位置', distance + '米');
		let result = distance < 100;
		if (isContinueAfterPause.value) {
			isContinueAfterPause.value = false;
			pauseDistance.value += calculateDistance(
				pauseMarker.value.latitude,
				pauseMarker.value.longitude,
				location.latitude,
				location.longitude
			);
			pauseMarker.value = {};
			return true;
		}
		return result;
	}

	// 更新軌跡線
	function updatePolyline() {
		if (trackPoints.value.length < 2) return;

		polyline.value = [
			{
				points: trackPoints.value.map((point) => ({
					latitude: point.latitude,
					longitude: point.longitude,
				})),
				color: '#007AFF',
				width: 4,
				arrowLine: true,
			},
		];
	}

	// 重置狀態(tài)
	function resetState() {
		trackPoints.value = [];
		polyline.value = [];
		markers.value = [];
		startTime.value = null;
		currentTime.value = Date.now(); // 清除時(shí)也重置當(dāng)前時(shí)間

		// 重置暫停相關(guān)狀態(tài)
		isPause.value = false;
		pauseStartTime.value = null;
		totalPauseTime.value = 0;
		isContinueAfterPause.value = false;
		pauseNum.value = 0;
		pauseDistance.value = 0;
		pauseMarker.value = {};
	}

	// 停止位置監(jiān)聽
	function stopLocationTracking() {
		console.log('調(diào)用停止位置監(jiān)聽函數(shù),當(dāng)前狀態(tài):', {
			isTracking: isTracking.value,
			isPause: isPause.value,
			markersCount: markers.value.length,
		});

		// 防止重復(fù)調(diào)用
		if (!isTracking.value) {
			console.log('已經(jīng)在停止?fàn)顟B(tài),跳過重復(fù)調(diào)用');
			return;
		}

		uni.stopLocationUpdate({
			success: async () => {
				console.log('停止監(jiān)聽位置變化成功');
				isTracking.value = false;
				stopTimer(); // 停止定時(shí)器

				// 移除位置變化監(jiān)聽
				uni.offLocationChange();

				// 重置暫停相關(guān)狀態(tài)
				isPause.value = false;
				pauseStartTime.value = null;
				// 注意:這里不重置 totalPauseTime,因?yàn)橥V褂涗洉r(shí)應(yīng)該保留總暫停時(shí)間用于顯示

				// 每次停止記錄時(shí)都添加結(jié)束點(diǎn)標(biāo)記
				await getCurrentLocation();
				addMarker({
					latitude: mapCenter.value.latitude,
					longitude: mapCenter.value.longitude,
					id: new Date().getTime(),
					content: '結(jié)束點(diǎn)',
				});

				uni.showToast({
					title: '已停止記錄',
					icon: 'none',
				});
			},
			fail: (err) => {
				console.error('停止監(jiān)聽位置變化失敗:', err);
			},
		});
	}

	// 保存軌跡記錄
	function saveTrack() {
		let saveData = {
			id: new Date().getTime(),
			mapCenter: mapCenter.value,
			markers: markers.value,
			polyline: polyline.value,
			viewModeTotalDistance: totalDistance.value,
			viewModeFormatDuration: formatDuration.value,
			viewModeAverageSpeed: averageSpeed.value,
		};
		console.log('保存軌跡記錄', saveData);
		let trackData = uni.getStorageSync('trackData') || [];
		trackData.push(saveData);
		uni.setStorageSync('trackData', trackData);
		uni.showToast({
			title: '軌跡記錄已保存',
			icon: 'success',
		});
		setTimeout(() => {
			uni.reLaunch({
				url: `/pages/home/index`,
			});
		}, 1000);
	}
</script>

<style lang="scss" scoped>
	.container {
		position: relative;
		width: 100%;
		height: 100vh;
	}

	.map {
		width: 100%;
		height: 100%;
	}

	.operate-box {
		position: absolute;
		top: 0;
		left: 0;
		z-index: 100;
		width: 100%;
		padding: 20rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		flex-direction: column;
	}

	.mode-panel {
		background: rgba(255, 255, 255, 0.95);
		border-radius: 12rpx;
		padding: 15rpx;
		box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
		margin-bottom: 20rpx;
	}
	.mode-item {
		display: flex;
		align-items: center;
		margin-bottom: 10rpx;

		&:last-child {
			margin-bottom: 0;
		}
	}
	.mode-label {
		font-size: 26rpx;
		color: #666;
		margin-right: 10rpx;
	}
	.mode-switch {
		display: flex;
		align-items: center;
		background: #f0f0f0;
		border-radius: 15rpx;
		padding: 6rpx 10rpx;
		switch {
			margin: 0 10rpx;
		}
	}
	.mode-text {
		font-size: 24rpx;
		color: #333;
		padding: 4rpx 10rpx;
		border-radius: 10rpx;

		&.active {
			background: #007aff;
			color: white;
		}
	}

	.control-panel {
		display: flex;
		justify-content: center;
		flex-wrap: wrap;
		gap: 10rpx;
		width: 100%;
	}
	.control-btn {
		padding: 10rpx 20rpx;
		background: rgba(255, 255, 255, 0.9);
		border: 1px solid #ddd;
		border-radius: 22rpx;
		font-size: 32rpx;
		color: #333;
		display: flex;
		justify-content: center;
		align-items: center;

		&.active {
			background: #007aff;
			color: white;
			border-color: #007aff;
		}

		&:disabled {
			opacity: 0.5;
		}
	}

	.pause-btn {
		background: rgba(255, 193, 7, 0.9);
		color: #fff;
		border-color: #ffc107;

		&.pause-active {
			background: rgba(76, 175, 80, 0.9);
			color: white;
			border-color: #4caf50;
		}
	}

	.info-panel {
		position: absolute;
		bottom: 20rpx;
		left: 20rpx;
		right: 20rpx;
		background: rgba(255, 255, 255, 0.95);
		border-radius: 12rpx;
		padding: 15rpx;
		box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
		z-index: 100;
	}

	.pause-status {
		text-align: center;
		margin-bottom: 10rpx;
		padding: 8rpx;
		background: rgba(255, 193, 7, 0.1);
		border-radius: 8rpx;
		border: 1px solid rgba(255, 193, 7, 0.3);
	}

	.pause-text {
		font-size: 26rpx;
		color: #ff9800;
		font-weight: 500;
	}
	.info-item {
		display: flex;
		justify-content: space-between;
		align-items: center;
		margin-bottom: 8rpx;

		&:last-child {
			margin-bottom: 0;
		}
	}
	.info-label {
		font-size: 28rpx;
		color: #666;
	}
	.info-value {
		font-size: 32rpx;
		color: #333;
		font-weight: 500;
	}
</style>

注意:getSetting 函數(shù)是封裝的權(quán)限授權(quán)功能,查看我的這篇文章:http://m.fzitv.net/javascript/364386r13.htm

總結(jié)

到此這篇關(guān)于uniapp封裝地圖運(yùn)動(dòng)軌跡的文章就介紹到這了,更多相關(guān)uniapp封裝地圖運(yùn)動(dòng)軌跡內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決vue中使用swiper插件問題及swiper在vue中的用法

    解決vue中使用swiper插件問題及swiper在vue中的用法

    Swiper是純javascript打造的滑動(dòng)特效插件,面向手機(jī)、平板電腦等移動(dòng)終端。這篇文章主要介紹了解決vue中使用swiper插件及swiper在vue中的用法,需要的朋友可以參考下
    2018-04-04
  • 詳解vue.js組件化開發(fā)實(shí)踐

    詳解vue.js組件化開發(fā)實(shí)踐

    本篇文章主要介紹了vue.js組件化開發(fā)實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • 解決vue-photo-preview 異步圖片放大失效的問題

    解決vue-photo-preview 異步圖片放大失效的問題

    這篇文章主要介紹了解決vue-photo-preview 異步圖片放大失效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • vue如何實(shí)現(xiàn)級(jí)聯(lián)選擇器功能

    vue如何實(shí)現(xiàn)級(jí)聯(lián)選擇器功能

    這篇文章主要介紹了vue如何實(shí)現(xiàn)級(jí)聯(lián)選擇器功能問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Vue+Echarts實(shí)現(xiàn)簡(jiǎn)單折線圖

    Vue+Echarts實(shí)現(xiàn)簡(jiǎn)單折線圖

    這篇文章主要為大家詳細(xì)介紹了Vue+Echarts實(shí)現(xiàn)簡(jiǎn)單折線圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue中設(shè)置echarts寬度自適應(yīng)的代碼步驟

    vue中設(shè)置echarts寬度自適應(yīng)的代碼步驟

    這篇文章主要介紹了vue中設(shè)置echarts寬度自適應(yīng)的問題及解決方案,常常需要做到echarts圖表的自適應(yīng),一般是根據(jù)頁(yè)面的寬度做對(duì)應(yīng)的適應(yīng),本文記錄一下設(shè)置echarts圖表的自適應(yīng)的步驟,需要的朋友可以參考下
    2022-09-09
  • Vue使用鼠標(biāo)在Canvas上繪制矩形

    Vue使用鼠標(biāo)在Canvas上繪制矩形

    這篇文章主要介紹了Vue使用鼠標(biāo)在Canvas上繪制矩形,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • vue子傳父關(guān)于.sync與$emit的實(shí)現(xiàn)

    vue子傳父關(guān)于.sync與$emit的實(shí)現(xiàn)

    這篇文章主要介紹了vue子傳父關(guān)于.sync與$emit的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • vue3中使用keepAlive緩存路由組件不生效的問題解決

    vue3中使用keepAlive緩存路由組件不生效的問題解決

    這篇文章主要介紹了vue3中使用keepAlive緩存路由組件不生效的問題解決,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-06-06
  • Vuepress生成文檔部署到gitee.io的注意事項(xiàng)及說明

    Vuepress生成文檔部署到gitee.io的注意事項(xiàng)及說明

    這篇文章主要介紹了Vuepress生成文檔部署到gitee.io的注意事項(xiàng)及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評(píng)論

临沂市| 舟曲县| 琼海市| 襄汾县| 梁河县| 遂宁市| 吉木萨尔县| 崇明县| 云南省| 福泉市| 文安县| 阿荣旗| 阜新| 阿拉善右旗| 黄平县| 梓潼县| 博爱县| 光山县| 江北区| 盖州市| 广灵县| 兰州市| 葵青区| 凤凰县| 望奎县| 马关县| 四会市| 灌南县| 洛浦县| 大关县| 沙坪坝区| 克东县| 宜君县| 双城市| 南川市| 徐汇区| 平乐县| 修武县| 施秉县| 抚顺市| 什邡市|