uniapp使用webview调用谷歌地图(小程序+app端)_uniapp使用谷歌地图
前言
适用小程序和app端;具体功能可以搜索地址,选中地址返回。
一.前期准备
1.谷歌地图需要翻墙,否则无法加载。需要的翻墙软件自己备好,后续在模拟器测试也可以用到。
2.申请谷歌地图密钥
平台地址:https://developers.google.cn/maps/gmp-get-started
选择Maps JavaScript API
如需使用搜索地址则需开启,启用Places API(原先旧的api,在H5使用可能出现跨域问题,如后端可以解决,可直接使用这个)和Places API(New)(新的api,返回报错403)
二.相关代码
1.uniapp代码
点击选择地址页面
跳转地图显示页面
这里我看别人可以使用放置在本项目的html文件(例如/hybrid/html/map.html),但是我引用本地的没效果,后面就替换成线上的了。
但是这里你可以在本地运行html文件,然后使用本地ip调用可以做调试用
注意:
1.这里的@message=\"postMessageFun\"方法是接收来自html页面的返回值。
2.如果需要在模拟器校验app效果,需要换成线上地址。
2.html文件
这里引入了vue,有些是vue写法的
<!DOCTYPE html><html style=\"width: 100vw;height: 100vh;\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><script src=\"https://cdn.jsdelivr.net/npm/vue/dist/vue.js\"></script><link rel=\"stylesheet\" href=\"https://unpkg.com/element-ui/lib/theme-chalk/index.css\"><script src=\"https://unpkg.com/element-ui/lib/index.js\"></script><link rel=\"stylesheet/less\" type=\"text/css\" href=\"./css/map.less\" /><script src=\"https://cdn.jsdelivr.net/npm/less\"></script><script src=\"https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js\"></script></head><body><div id=\"app\" class=\"popup\"><div class=\"tools\"><i class=\"el-icon-circle-close close-icon\" @click=\"close\"></i><el-button type=\"primary\" class=\"tools-btn\" @click=\"confirm\">Confirm</el-button></div><div class=\"map\"><div id=\"googleMap\"></div></div><div class=\"box\"><div class=\"label\"><i class=\"el-icon-search search-icon\"></i><input v-model=\"searchAddress\" type=\"text\" placeholder=\"search place\"placeholder-style=\"color:#b8b8b8;\" /></div><div class=\"lists\"><div class=\"list\" v-for=\"(item, index) in list\"><div class=\"radio-box\"><span class=\"radio-name\">{{ item.name }}</span><span class=\"radio-text\">{{ item.formatted_address }}</span></div><el-radio v-model=\"current\" :label=\"index.toString()\" @input=\"radioChange\"> </el-radio></div></div></div></div></body><script type=\"text/javascript\" src=\"https://res.wx.qq.com/open/js/jweixin-1.4.0.js\"></script><script type=\"text/javascript\" src=\"https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js\"></script><script>// 初始化地图var map;function initMap() {//页面传过来的参数arrvar mapPointResult = GetUrlParam(\'arr\') ? JSON.parse(decodeURIComponent(GetUrlParam(\'arr\'))) : [{lng: 103.53028,lat: 10.62592}];var centerPoint = {lat: mapPointResult[0].lat,lng: mapPointResult[0].lng,};map = new google.maps.Map(document.getElementById(\'googleMap\'), {center: centerPoint,zoom: 16});var marker = new google.maps.Marker({position: centerPoint,map: map,icon: {url: \'https://now.guua.com/attachs/default/location_shop.png\',scaledSize: new google.maps.Size(30, 30),origin: new google.maps.Point(0, 0),anchor: new google.maps.Point(0, 0)}});}// 处理URL参数function GetUrlParam(paraName) {var url = window.location.href;var arrObj = url.split(\"?\");if (arrObj.length > 1) {var arrPara = arrObj[1].split(\"&\");var arr;for (var i = 0; i < arrPara.length; i++) {arr = arrPara[i].split(\"=\");if (arr != null && arr[0] == paraName) {return arr[1];}}return \"\";} else {return \"\";}}// 定位(这里如果需要搜索选中地址后定位到选中位置,可以调用这个方法)// function searchAddress() {// var address = \'北京\';// var geocoder = new google.maps.Geocoder();// geocoder.geocode({// \'address\': address// }, function(results, status) {// if (status === \'OK\') {// var latlng = results[0].geometry.location;// var map = new google.maps.Map(document.getElementById(\'googleMap\'), {// zoom: 15,// center: latlng// });// var marker = new google.maps.Marker({// position: latlng,// map: map,// title: \'Address Location\'// });// } else {// alert(\'Geocode was not successful for the following reason: \' + status);// }// });// }</script><script src=\"https://maps.googleapis.com/maps/api/js?key=你的秘钥&callback=initMap\"async defer></script><script>new Vue({el: \'#app\',data: {googleKey: \'你的秘钥\',searchAddress: \'\',current: -1,list: [],curPlace: false},watch: {searchAddress: {handler(newV) {if (newV) {this.searchFindAddress();} else {this.list = [];}},deep: true}},methods: {// 关闭地图close() {uni.navigateBack({delta: 1});},// 选中地址confirm() {let thar = this;if (this.curPlace) {let curPlace = JSON.parse(this.curPlace);let latlng = {lat: curPlace.geometry.location.lat,lng: curPlace.geometry.location.lng};let url =`https://maps.googleapis.com/maps/api/geocode/json?key=${this.googleKey}&latlng=${latlng.lat},${latlng.lng}&language=en`;axios.get(url).then(res => {console.log(\'确定选中地址回调\', res)if (res.status == 200) {let resData = res.data;let compound_code = resData.plus_code.compound_code;compound_code = compound_code.split(\' \');let obj = {compound_code: compound_code[1],latlng: latlng,// name: curPlace.namename: curPlace.formatted_address};//选中返回uniapp的值uni.postMessage({data: obj});thar.close();}}).catch(err => {console.log(err)})} else {alert(\'请先选中地址!!!\')}},//搜索searchFindAddress() {let thar = this;this.current = -1;this.list = [];// 原有的接口出现跨域问题(新的api需要注册才可以用)// let url =// `https://maps.googleapis.com/maps/api/place/textsearch/json?key=${this.googleKey}&query=${encodeURIComponent(this.searchAddress)}&language=en`;// 可以调用,但是返回的信息不完整(这里没有返回具体的地址)let url =`https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(this.searchAddress)}&key=${this.googleKey}`;axios.get(url).then(response => {console.log(\'搜索地址\', response);if (response.data.status === \'OK\') {let resData = response.data.results;thar.list = resData;} else {thar.list = [];}}).catch(error => {// this.errorMessage = \'请求失败,请稍后再试\';console.error(\'请求失败\', error);});},//列表选中地址radioChange(e) {this.current = e;this.curPlace = JSON.stringify(this.list[this.current]);},}})</script></html>
注意的点:
1.需要和uniapp页面通信的话,必须引入这两个SDK,并且需要放在body后面,而且微信SDK必须在前面。
2.谷歌搜索api问题
这里后续我让后端给我处理了。
https://maps.googleapis.com/maps/api/place/textsearch/json?key=你的密钥&query=搜索地址&language=en
这个是旧的api,但是在H5页面使用会出现跨域问题,最好是让后端给解决一下,直接给你一个接口。
https://places.googleapis.com/v1/places:searchText是新的api,这里调用会出现403报错。这里确定配置平台已启用了Places API(New),不晓得是哪里不行,求知道的大佬告知。
以下为调用的代码片段和报错信息
let url = `https://places.googleapis.com/v1/places:searchText`;axios.post(url, {textQuery: this.searchAddress,\'X-Goog-FieldMask\': \'*\',\'X-Goog-Api-Key\': \'你的密钥\'}).then(response => {console.log(\'搜索地址\', response);if (response.data.status === \'OK\') {let resData = response.data.results;thar.list = resData;} else {thar.list = [];}}).catch(error => {// this.errorMessage = \'请求失败,请稍后再试\';console.error(\'请求失败\', error);});
三.效果图
网页端
小程序
app
四.其他
这里如果想在模拟器测试,需要在模拟器安装跨域工具(和在真机安装配置一样)。
这里配置自己搜索下进行配置就好。
开启后,就能进去app校验地图效果了。