uniapp开发app使用谷歌地图(ios跟安卓)

前提条件:

谷歌地图需要翻墙,否则无法加载

谷歌地图说明

文档地址:概览 | Maps JavaScript API | Google for Developers

  • 设置地图语言
html 复制代码
<script async
    src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&language=ja&callback=initMap">
</script>

文档地址:将地图本地化 | Maps JavaScript API | Google for Developers

第一种方法(web-view):

web-view 是一个 web 浏览器组件,可以用来承载网页的容器,会自动铺满整个页面(nvue 使用需要手动指定宽高),一般都会用nvue,否则默认占满页面

官网说明:web-view | uni-app官网

  • 展示目录结构:

index.nvue

javascript 复制代码
<template>
	<view>
		<view style="height: 100rpx;">222222222</view>
		<view class="" v-if="isShow">
			<web-view style="background-color: #fafafa;" ref="webview" :style="{ height: statusBarHeight + 'px'}"
				@onPostMessage="getMessage" :src="webUrl"></web-view>
		</view>
	</view>
</template>

<script>
	/**
	 * 
	 * 请看这里 
	 * source :来源 根据上个界面传来的type值 实现不同的功能  
	 * 
	 * */
	import Vue from 'vue';
	export default {
		data() {
			return {
				statusBarHeight: 500, //可视屏幕的高度
				webUrl: '',
				isShow: false,
				lat:'',
				lng:'' ,
				source: "",
			};
		},
		onLoad(e) {
			console.log(e.type)
			this.source = e.type;
			// #ifdef APP-PLUS
			this.getlocetion();
			// #endif
		},
		methods: {
			getlocetion() {
				const self = this;
				self.lat = '39.906217';
				self.lng = '116.3912757';
				self.webUrl = '/hybrid/html/maps/index' + self.source + '.html?lat=' + self.lat +
					'&lng=' +
					self.lng;
				self.isShow = true
			}
		}
	};
</script>

<style>
	
</style>

index1.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta name="viewport"
			content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=0" />
		<link href="http://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet" type="text/css">
		<title>谷歌地图-初始化地图</title>
		<link rel="stylesheet" type="text/css" href="./css/index.css" />
		<script src="./js/lib/common.js"></script>
	</head>
	<body>
		<!-- 地图 -->
		<div id="map"></div>
		<!-- css loading动画 -->
		<div class="loader" id="loader"></div>
	</body>
	<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
	<script
		src="https://maps.googleapis.com/maps/api/js?key=xxxxxxxx&libraries=places&language=zh-TW&callback=initMap"
		async defer></script>
	<script src="./js/index1.js"></script>
</html>

index1.js

javascript 复制代码
var lats = getQueryVariable('lat') * 1;
var lngs = getQueryVariable('lng') * 1;
console.log(lats,lngs)
var zoom = 15; //地图缩放比例
var coords = ""

/**
 * 初始化
 * 
 */
function initMap() {

	if (lats && lngs) {
		coords = {
			lat: lats,
			lng: lngs
		};
	} else {
		navigator.geolocation.getCurrentPosition(function(position) {
			coords = {
				lat: position.coords.latitude,
				lng: position.coords.longitude
			};
			lats = position.coords.latitude;
			lngs = position.coords.longitude
		});
	}
	map = new google.maps.Map(document.getElementById('map'), {
		zoom: zoom,
		center: coords,
		mapId: MAPID,
		animation: 'BOUNCE',
		language: 'zh-TW'
	});
	setTimeout(() => {
		LoadAnimation(false)
	}, 1000)

}
LoadAnimation(true)
window.initMap = initMap;

common.js --- 公共js

javascript 复制代码
/**
 * MapID
 * 
 * 
 * */
var MAPID = 'xxxxxxx'

/**
 * 
 * 获取url地址参数
 * 
 * */

function getQueryVariable(variable) {
	var query = decodeURI(window.location.search.substring(1));
	var vars = query.split("&");
	for (var i = 0; i < vars.length; i++) {
		var pair = vars[i].split("=");
		if (pair[0] == variable) {
			return pair[1];
		}
	}
	return (false);
}

/**
 * 加载动画
 * 
 */
function LoadAnimation(isFalse) {
	if (isFalse) {
		document.getElementById("loader").style.display = "inline";
	} else {
		document.getElementById("loader").style.display = "none";
	}

}

uni.webview.1.5.2.js 这个 JavaScript 文件为开发者提供了在 Uni-app 中使用 Webview 组件的丰富功能和接口,方便开发者在应用中集成和控制 web 页面

在网页中引入 Google Fonts 中的 Roboto 字体。Google Fonts 提供了大量免费的网页字体供开发者使用

上面代码就可以生成一个谷歌地图示例了

第二种方法(render.js)

renderjs是一个运行在视图层的js。它比WXS更加强大。它只支持app-vue和web;

在视图层操作dom,运行 for web 的 js库

googleMap.vue

app繁体语言加载地图,绘制marker,绘制轨迹

javascript 复制代码
<template>
	<view class="trajectory OverallSty">
		<view class="content">
			<view id="container">
				<view class="loader" v-if="loaderSta"></view>
				<view style="width: 750rpx; height:650rpx;" :location="currLocation"
					:change:location="renderScript.receiveLoca" :Trace="currTrace"
					:change:Trace="renderScript.receiveTrace" id="renderScript"></view>
			</view>
		</view>
	</view>
</template>

<script>
	import {
		get,
		post
	} from '@/util/request/request.js'
	import localStorage from '@/util/commen/localStorage.js'
	import {
		onLoad
	} from "@dcloudio/uni-app"
	export default {
		data() {
			return {
				markers: [{
					id: 'begin',
					latitude: '',
					longitude: '',
					iconPath: "../../static/img/map/place.png",
					width: 30,
					height: 30
				}],
				polylines: [],
				center_lat: '',
				center_lng: '',
				userInfo: JSON.parse(localStorage.get('userInfo')),
				projInfo: JSON.parse(localStorage.get('projInfo')),
				getWorkerSignsInformation: {},
				searchBeginTime: '',
				searchEndTime: '',
				workerInfo: null,
				currLocation: {},
				currTrace: [],
				loaderSta: true
			}
		},
		onLoad(options) {
			let data = JSON.parse(decodeURIComponent(options.data));
			this.workerInfo = data
		},
		mounted() {
			let _this = this
			setTimeout(() => {
				_this.loaderSta = false
			}, 1500);
			this.getWorkerSignsInformationFun()
		},
		methods: {
			getWorkerLocus() {
				let _this = this
				get('/proj/smartBracelet/getWorkerLocus', {
					'projId': _this.projInfo.proId,
					'workerId': _this.workerInfo.workerId,
					'searchBeginTime': _this.searchBeginTime,
					'searchEndTime': _this.searchEndTime
				}, {
					'token': localStorage.get('token'),
					'uid': _this.userInfo.userId
				}).then(res => {
					let data = res.data.result
					const points = data.lon.map((lon, index) => {
						return {
							lat: parseFloat(data.lat[index]),
							lng: parseFloat(lon)
						}
					});
					if (points[0]?.lat == "" || points[0]?.lng == "" ||
						points[0]?.lat == undefined || points[0]?.lng == undefined) {
						_this.$refs.messagePopup.showMessage('warn', '未查詢到軌跡', 'top')
						return
					}
					_this.currTrace = points
				}).catch(err => {
					console.error(err);
				});
			},
			getWorkerSignsInformationFun() {
				let _this = this
				get('/proj/smartBracelet/getWorkerSignsInformation', {
					'projId': _this.projInfo.proId,
					'workerId': _this.workerInfo.workerId
				}, {
					'token': localStorage.get('token'),
					'uid': _this.userInfo.userId
				}).then(res => {
					_this.getWorkerSignsInformation = res.data?.result
					if (_this.getWorkerSignsInformation?.lat == undefined || _this.getWorkerSignsInformation
						?.lon == undefined) {
						_this.$refs.messagePopup.showMessage('warn', '未獲取定位信息', 'top')
						_this.center_lat = '39.906217';
						_this.center_lng = '116.3912757';
						_this.markers[0].latitude = '39.906217';
						_this.markers[0].longitude = '116.3912757';
						return
					}
					_this.currLocation = res.data.result
					_this.center_lat = _this.getWorkerSignsInformation.lat;
					_this.center_lng = _this.getWorkerSignsInformation.lon;
					_this.markers[0].latitude = _this.getWorkerSignsInformation.lat;
					_this.markers[0].longitude = _this.getWorkerSignsInformation.lon;
				}).catch(err => {
					console.error(err);
				});
			}
		}
	};
</script>
<script module="renderScript" lang="renderjs">
	var meMarker = []
	var polylinePath = null
	export default {
		data() {
			return {
				map: {},
				receiveLocaDate: {
					lat: '39.906217',
					lon: '116.3912757'
				},
				receiveTraceDate: []
			};
		},
		mounted() {
			let _this = this
			const script = document.createElement('script')
			script.src =
				'https://maps.googleapis.com/maps/api/js?key=xxxxxxxx&language=zh-TW&callback=initMap'
			window.initMap = function() {
				setTimeout(() => {
					console.log('renderScript')
					_this.initAmap()
				}, 1500);
			};
			document.head.appendChild(script)
		},
		methods: {
			initAmap() {
				let _this = this
				console.log('initAmap')
				_this.map = new google.maps.Map(document.getElementById("renderScript"), {
					center: {
						lat: parseFloat(_this.receiveLocaDate.lat),
						lng: parseFloat(_this.receiveLocaDate.lon)
					},
					zoom: 16
				});
				_this.setMePositioning()
			},
			setMePositioning() {
				let _this = this
				const marker = new google.maps.Marker({
					position: {
						lat: parseFloat(_this.receiveLocaDate.lat),
						lng: parseFloat(_this.receiveLocaDate.lon)
					},
					icon: {
						url: "https://maps.gstatic.com/mapfiles/ms2/micons/red.png",
						scaledSize: new google.maps.Size(50, 50)
					},
					map: _this.map
				});
				meMarker.push(marker)
			},
			receiveLoca(newValue, oldValue, ownerInstance, instance) {
				let _this = this
				if (JSON.stringify(newValue) != '{}' && newValue.length != 0) {
					_this.receiveLocaDate = newValue
				}
			},
			receiveTrace(newValue, oldValue, ownerInstance, instance) {
				let _this = this
				if (JSON.stringify(newValue) != '{}' && newValue.length != 0) {
					console.log('触发了',newValue,newValue.length)
					for (let i = 0; i < meMarker.length; i++) {
						meMarker[i].setMap(null);
					}
					if(polylinePath != null){
						polylinePath.setMap(null);
					}
					_this.map.setZoom(20);
					const marker1 = new google.maps.Marker({
						position: {
							lat: parseFloat(newValue[0].lat),
							lng: parseFloat(newValue[0].lng)
						},
						icon: {
							url: "static/img/map/icon_start.png",
							scaledSize: new google.maps.Size(20, 20)
						},
						map: _this.map
					});
					meMarker.push(marker1)
					const marker2 = new google.maps.Marker({
						position: {
							lat: parseFloat(newValue[newValue.length - 1].lat),
							lng: parseFloat(newValue[newValue.length - 1].lng)
						},
						icon: {
							url: "static/img/map/icon_end.png",
							scaledSize: new google.maps.Size(20, 20)
						},
						map: _this.map
					});
					meMarker.push(marker2)
					polylinePath = new google.maps.Polyline({
						path: newValue,
						geodesic: false,
						strokeColor: '#41d9b7',
						strokeOpacity: 1,
						strokeWeight: 8,
						editable: false,
						draggable: false,
					});
					polylinePath.setMap(_this.map)
					let pos = {
						lat: parseFloat(newValue[0].lat),
						lng: parseFloat(newValue[0].lng)
					}
					_this.map.setCenter(pos)
				}
			}
		}
	}
</script>

<style scoped>
	/* 动画 */
	.trajectory .loader {
		position: fixed;
		z-index: 99;
		border: 8px solid #f3f3f3;
		border-top: 8px solid #ea4335;
		border-radius: 50%;
		width: 80px;
		height: 80px;
		animation: spin 2s linear infinite;
		position: absolute;
		top: 50%;
		left: 50%;
		margin-left: -90rpx;
		margin-top: 320rpx;
		transform: translate(-50%, -50%);
	}

	@keyframes spin {
		0% {
			transform: rotate(0deg);
		}

		100% {
			transform: rotate(360deg);
		}
	}
</style>

遇到的问题

  • manifest.json中不用勾选map模块,否则google地图打包时会模块冲突,导致打包失败

例如报错日志:

javascript 复制代码
* What went wrong:
Execution failed for task ':app:checkReleaseDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
> Duplicate class com.google.android.gms.actions.ItemListIntents found in modules jetified-play-services-basement-18.0.0-runtime (com.google.android.gms:play-services-basement:18.0.0) and jetified-play-services-basement-18.0.0-runtime (play-services-basement-18.0.0.aar)
Duplicate class com.google.android.gms.actions.NoteIntents found in modules jetified-play-services-basement-18.0.0-runtime (com.google.android.gms:play-services-basement:18.0.0) and jetified-play-services-basement-18.0.0-runtime (play-services-basement-18.0.0.aar)
Duplicate class com.google.android.gms.actions.ReserveIntents found in modules jetified-play-services-basement-18.0.0-runtime (com.google.android.gms:play-services-basement:18.0.0) and jetified-play-services-basement-18.0.0-runtime (play-services-basement-18.0.0.aar)   
  • InvalidValueError: at index 0: not a LatLng or LatLngLiteral with finite coordinates: in property lat: not a number a

经纬度坐标格式不正确,导致 Google 地图 API 无法识别,确保提供的经纬度值是有效的数字,确保经纬度值的类型是 number

其他

UNiAPP中使用render.js绘制高德地图文章推荐:

UNiAPP中使用render.js绘制高德地图 - 掘金 (juejin.cn)

HBuilderX历史版本:历史版本 - HBuilderX 文档 (dcloud.net.cn)
谷歌地图插件:谷歌示例大全、各种谷歌地图案例 - DCloud 插件市场

相关推荐
小白CAD24 分钟前
前端vue打印后端对象为[object,object]
前端·javascript·vue.js
续亮~3 小时前
6、Redis系统-数据结构-05-整数
java·前端·数据结构·redis·算法
顶顶年华正版软件官方5 小时前
剪辑抽帧技巧有哪些 剪辑抽帧怎么做视频 剪辑抽帧补帧怎么操作 剪辑抽帧有什么用 视频剪辑哪个软件好用在哪里学
前端·音视频·视频·会声会影·视频剪辑软件·视频剪辑教程·剪辑抽帧技巧
MarkHD5 小时前
javascript 常见设计模式
开发语言·javascript·设计模式
托尼沙滩裤6 小时前
【js面试题】js的数据结构
前端·javascript·数据结构
不熬夜的臭宝6 小时前
每天10个vue面试题(一)
前端·vue.js·面试
朝阳396 小时前
vue3【实战】来回拖拽放置图片
javascript·vue.js
不如喫茶去6 小时前
VUE自定义新增、复制、删除dom元素
前端·javascript·vue.js
长而不宰6 小时前
vue3+electron项目搭建,遇到的坑
前端·vue.js·electron
阿垚啊7 小时前
vue事件参数
前端·javascript·vue.js