uniapp 中使用天地图,安卓端、h5

发布于:2025-02-23 ⋅ 阅读:(13) ⋅ 点赞:(0)

 

背景:项目需要将高德地图换成天地图,pc端已经更换,但app端用uniapp写的,就有点茫然了,毕竟uniapp官方给出的地图组件也不支持啊,网上找吧,也没什么例子,算了,自己写吧。

 思路:使用 uniapp中 renderjs 来引入使用天地图;注意:renderjs中不能使用任何uniapp的api,h5中可能没事 但app就不行了。网上也有使用 <web-view> 直接引入地图的,但看他们说样式不好改,就没使。

代码如下:

  1.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 

<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 接受变量值,并获取数据 渲染地图

<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;  安装转换插件

使用如下:

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博客

还有就是,这代码,可能少括号。