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 插件市场

相关推荐
m0_74825488几秒前
DataX3.0+DataX-Web部署分布式可视化ETL系统
前端·分布式·etl
ZJ_.12 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
GIS开发特训营16 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood42 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端44 分钟前
0基础学前端-----CSS DAY9
前端·css
joan_851 小时前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
还是大剑师兰特1 小时前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo6172 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_748248942 小时前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5