
背景:项目需要将高德地图换成天地图,pc端已经更换,但app端用uniapp写的,就有点茫然了,毕竟uniapp官方给出的地图组件也不支持啊,网上找吧,也没什么例子,算了,自己写吧。
思路:使用 uniapp中 renderjs 来引入使用天地图;注意:renderjs中不能使用任何uniapp的api,h5中可能没事 但app就不行了。网上也有使用 <web-view> 直接引入地图的,但看他们说样式不好改,就没使。代码如下:
1.html 中创建地图容器
html
<template>
<view>
<!--地图容器-->
<view id="mapDiv" style="width:100vw;height:100vh,z-index:1}"></view>
<!--详情-->
<view class="detail-wrap" v-if="isShow">
<view class="detail-title">
<text class="text">{{obj.name}}</text>
</view>
<view class="detaile-content">
<text class="text">微站编码:{{obj.mn}}</text>
</view>
</view>
<!--renderjs-->
<!--向renderjs 传递 token属性-->
<view class="" :prop="token" :change:prop="renderScript.tokenChange"></view>
<!--点击时 触发renderjs getInfo()方法-->
<view id="info" @click="renderScript.getInfo"></view>
</view>
</template>
2.普通 js
javascript
<script>
export default {
data(){
return {
obj:{},
token:uni.getStorageSync("token")
}
},
methods:{
markerClick(item){
this.obj = item
this.isShow = true;
},
errorMsg({code,msg}){
uni.showToast({
icon: "none",
title: msg
})
},
}
}
</script>
3.renderjs 接受变量值,并获取数据 渲染地图
javascript
<script module="renderScript" lang="renderjs">
import axios from 'axios'; // 调接口用
import {exchangeGdToTdt} from "@/utils/index.js"; // 坐标转换
export default {
data() {
return {
token:'',
}
},
mounted(){
// 加载地图必须放到异步执行,否则地图放大后会没有标注图层,不知道为什么
setTimeout(()=> {
this.initMap() // 初始化地图
}, 0);
},
methods: {
//接受普通js 传递的token值,因为我这里接口需要token
tokenChange(newValue, oldValue, ownerVm, vm) {
this.token = newValue // 它会早于mounted执行
},
// 引入天地图API脚本
initMap() {
const script = document.createElement('script');
script.src = "http://api.tianditu.gov.cn/api?v=4.0&tk=你的天地图密钥";
script.onload = () => {
this.createMap();
};
document.body.appendChild(script);
},
// 初始化地图
createMap() {
this.map = new T.Map('mapDiv',{
zoom:11,
maxZoom:18,
minZoom:10,
center:new T.LngLat(116.68098, 40.14166)
});
// 点聚合配置
this.markerClusterer = new T.MarkerClusterer(this.map,{
girdSize:40, // 每个聚合区域大小为 40,默认60,越小分的越精细聚合点越多
maxZoom:3,
})
const that = this;
this.map.on('zoomend', function(e) {
const zoom = that.map.getZoom()
// 天地图最大缩放级别 18,但到达18时,好多聚合点还没展开呢,所以手动缩小网格区域,使聚合点展开
if(zoom>=17){
that.markerClusterer.setGridSize(3)
}else{
if(that.markerClusterer.getGridSize()<40){
that.markerClusterer.setGridSize(40)
}
}
})
// 获取页面数据
// 这样触发 getInfo方法 是为了获取 ownerInstance对象,如果使用this.getInfo() 获取不到
document.getElementById("info").click()
},
// 获取页面点数据
async getInfo(event, ownerInstance) {
let res = await axios({
method: "post",
url: outletMapData,
data,
headers: {
'Authorization': 'Bearer' + ' ' + this.token
},
})
if (res.data.code == 202) {
// 触发普通js errorMsg 方法
ownerInstance.callMethod('errorMsg', {code:res.data.code,msg:''})
}
if (res.data.code !== 200) {
ownerInstance.callMethod('errorMsg', {code:res.data.code,msg:res.data.msg})
return
}
const arr = res.data.data;
this.positions = arr.map(item => {
// 高德地图转天地图坐标
const obj = exchangeGdToTdt(item.lnggcj,item.latgcj)
item.lnggcj = obj.lnggcj;
item.latgcj = obj.latgcj;
return {
id: item.outletid,
...item
}
})
if (this.positions.length > 0 && this.positions[0].latgcj && this.positions[0].lnggcj) {
this.latitude = this.positions[0].latgcj;
this.longitude = this.positions[0].lnggcj;
this.map.centerAndZoom(new T.LngLat(this.longitude,this.latitude),11)
}
// 清空聚合数据
if(this.markerClusterer){
this.markerClusterer.clearMarkers()
}
//渲染数据
if (this.positions.length > 0) {
this.addMarkers(this.positions,ownerInstance)
}
},
// 创建marker标记
addMarkers(positions,ownerInstance) {
const markers = []
for(let item of positions){
const marker = new T.Marker(
new T.LngLat(item.lnggcj,item.latgcj),
{
icon: new T.Icon({
iconUrl:require("../../../static/riverOutfall/dingweixiao.png"),
iconSize: new T.Point(28, 34),
}),
title:item.name,
item:{...item}
}
)
marker.on('click', function(e) {
const data = e.target.options
const lnglat = e.lnglat
const item = data.item
// 触发普通js markerClick 方法 传参:item
ownerInstance.callMethod('markerClick', item)
})
markers.push(marker)
}
this.markerClusterer.addMarkers(markers)
},
}
}
</script>
4.坐标转换
npm i gcoord; 安装转换插件
使用如下:
javascript
import gcoord from 'gcoord';
// 高德地图坐标转天地图坐标
export function exchangeGdToTdt(lng,lat){
if(!lng || !lat){
return {}
}
let wgsJson = gcoord.transform(
[lng,lat], // 经纬度坐标
gcoord.GCJ02, // 当前坐标系 高德 火星坐标
gcoord.WGS84 // 目标坐标系 天地图
);
return {
lnggcj: wgsJson[0],
latgcj: wgsJson[1]
};
}
普通 js 想调用 renderjs 中的方法,只能通过点击事件;renderjs向普通js传递数据 只能通过 ownerInstance 对象,所以 点击事件关联着 这两种js。目前这是我看到的结果,希望有帮到大家。如果大家有更好的办法,也可以告诉我呀。
一开始不是找半天例子找不着吗,结果 等我写完了,我就看到了个相关的例子。。。额,但我没仔细研究过,链接贴上,也许以后会用到:uni-app如何引入天地图并兼容app_uniapp 天地图-CSDN博客
还有就是,这代码,可能少括号。