前提条件:
谷歌地图需要翻墙,否则无法加载
谷歌地图说明
文档地址:概览 | Maps JavaScript API | Google for Developers
- 设置地图语言
<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
<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
<!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
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
/**
* 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";
}
}
- <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>是什么
uni.webview.1.5.2.js
这个 JavaScript 文件为开发者提供了在 Uni-app 中使用 Webview 组件的丰富功能和接口,方便开发者在应用中集成和控制 web 页面
- <link href="http://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet" type="text/css"> 是什么
在网页中引入 Google Fonts 中的 Roboto 字体。Google Fonts 提供了大量免费的网页字体供开发者使用
上面代码就可以生成一个谷歌地图示例了
第二种方法(render.js)
renderjs
是一个运行在视图层的js。它比WXS更加强大。它只支持app-vue和web;
在视图层操作dom,运行 for web 的 js库
googleMap.vue
app繁体语言加载地图,绘制marker,绘制轨迹
<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地图打包时会模块冲突,导致打包失败
例如报错日志:
* 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 插件市场