记一次在uniapp renderjs中使用高德地图

3,413 阅读3分钟

记一次在uniapp renderjs中使用高德地图

🍓 uniapp renderjs H5 高德地图

◢注意


​ 本文仅针对于使用uniapp开发的H5项目,对于app或小程序开发兼容问题请自行处理。

◢前言


​ 开发H5项目时,因为要用到地图,首先使用的是uniapp官方的<map>组件,但是用的过程中发现局限性很多,之前开发别的项目的时候也用过高德地图,所以选择了高德地图。但是目前搜索到的大多数都是基于高德地图2.0之前的版本,本文使用的是高德地图目前最新的版本,所以记录一下。

◢关于uniapp renderjs的使用


​ 先加载出高德地图,上代码

<template>
	<view>
		<view 
			id="amap" 
			:style="mapStyle" 
			class="amap-style" 
			:markers="markers" 
			:change:markers="amap.updateMarker"
			>
		</view>
	</view>
</template>

<!-- 高德地图 renderjs视图层 -->
<script module="amap" lang="renderjs">
	export default {
		data() {
			return {
				
			}
		},
		mounted() {
			console.log('renderjs mounted');
		},
		methods: {
			// 更新数据
			updateMarker(newVal) {
				console.log('renderjs 更新:', newVal);
				this.initMarkers();
			},
		},
	}
</script>

<!-- 逻辑层代码 -->
<script>
	export default {
		name: 'DetailsMap',
		data() {
			return {
				markers: [],
			},
		}
</script>
  1. renderjs script标签中的module对应需要绑定DOM的id
  2. 绑定的数据为逻辑层中的数据,我这里绑定的是逻辑层中的markers,在markers数据发生变化时,会主动触发绑定的视图层的更新函数。
  3. 这里说明一下,:markers="markers"也可以写成任何:[key]="markers"的形式,但是对应的触发函数的绑定也要改成对应的:change:[key]="[renderjs module].function"形式。比如我这里可以改成:props="markers" :change:props="amap.updateMarker",这样可以绑定多个数据。
  4. 其他renderjs相关请参考uniapp的官方说明及其提供的使用实例

◢关于高德地图的加载


​ 先上代码

<!-- 高德地图 renderjs视图层 -->
<script module="amap" lang="renderjs">
	let map = undefined;
	export default {
		data() {
			return {
				isMapLoadSuccess: false
			}
		},
		mounted() {
			console.log('renderjs mounted');
			// 清除地图数据
			this.reset();
			// 注意:异步回调函数的声明应该在 JSAPI 引入之前,函数名与callback=onLoad中对应
			if (!window.onLoad) {
				window.onLoad = () => {
					this.init();
				};
			} else {
				this.init();
			}
			// 异步加载高德地图 JSAPI 
			if (!window.AMap) {
				this.loadAMap();
			}
		},
		methods: {
			// 异步加载高德地图 JSAPI 
			loadAMap() {
				// 动态异步引入较大类库避免影响页面展示
				const myKey = '你申请的key';
				const myCode = "对应的秘钥";
				const url = `https://webapi.amap.com/maps?v=2.0&key=${myKey}&callback=onLoad`;
				const jsapi = document.createElement('script');
				jsapi.charset = 'utf-8';
				jsapi.src = url;
				document.head.appendChild(jsapi);
				// 安全密钥
				window._AMapSecurityConfig = {
					securityJsCode: myCode,
				};
				console.log('加载高德地图插件');
			},
			// 初始化
			init() {
				map = new AMap.Map('amap', this.mapDefaultOptions);

				map.on('complete', () => {
					console.log('地图加载完成');
					this.isMapLoadSuccess = true;
					this.initMarkers();
				})
			},
			// 地图相关数据初始化
			reset() {
				map && (map = undefined);
				// 如果有之前的数据,先清除

			},
			// 生成点聚合点位
			initMarkers() {
				if (!(this.isMapLoadSuccess && this.markers.length)) {
					return
				}
				// 你的代码执行地图相关操作

			},
			// 更新数据
			updateMarker(newVal) {
				console.log('renderjs 更新:', newVal);
				this.initMarkers();
			},
		},
	}
</script>
  1. 加载方式参照高德地图给出的异步加载实例
  2. 这里做了防止多次加载JSAPI的处理,但是我们挂载的加载完执行的onLoad函数只会执行一次,所以不刷新的情况下再次打开地图,onLoad函数不会再次触发,我们要通过判断条件去再次执行init函数。
  3. 因为renderjs视图层不支持vue的beforeDestroy、destroyed生命周期,所以清除地图相关数据放到mounted生命周期去执行。
  4. uniapp官方指出==H5 端逻辑层和视图层实际运行在同一个环境中,相当于使用 mixin 方式,可以直接访问逻辑层数据。==所以可以直接通过this去访问逻辑层中的数据。
  5. 关于==先网络请求再操作地图的顺序==问题:我自己处理的办法是在数据更新后和地图加载完成后都去执行相关操作,但是需要添加前置判断条件,防止地图没有加载完成就去执行操作。
  6. 地图的尺寸问题:可以通过uniapp的uni.getSystemInfoSync方法获取设备的屏幕高度,再将这个设置为地图的高度,以此实现占满整个屏幕。

◢关于高德地图的点聚合功能


// 加载点聚合插件
map.plugin(["AMap.MarkerCluster"], () => {
	cluster = new AMap.MarkerCluster(map, point, {
		gridSize: 80, // 聚合网格像素大小
		renderClusterMarker: (context) => { // 对聚合点位的渲染
            // 入参中有四个数据 count data indexs marker
			// console.log('context:', context);  
			// 修改聚合点位样式
			this.createClusterMarker(context);
			// 设置聚合点位点击事件
			const marker = context.marker;
			marker.on('click', (e) => {
				let mapZoom = map.getZoom();
				if (mapZoom < 20) {
					mapZoom += 2;
				}
				map.setZoomAndCenter(mapZoom, e.lnglat);
			})
		},
		renderMarker: ({
			data,
			marker
		}) => { // 对非聚合点位的渲染
            // 入参中有四个数据 count data indexs marker
			// console.log(context);  
			// 获取自己设置的name
			if(data[0].extData) {
				console.log(data[0].extData.name);
			}
			marker.setIcon(this.creatAMapIcon());
			marker.setAnchor('bottom-center');
			// 设置非聚合点位点击事件
			marker.on('click', (e) => {
				map.setCenter(e.lnglat);
				this.tapMarker();
			})
		}
	});
});
  1. 创建点聚合的MarkerCluster函数需要三个参数,其中第二个参数dataOptions我看到网上有传高德地图生成Marker的数组,但是我试了试并不行,这里提一嘴。
  2. 针对配置里的renderClusterMarkerrenderMarker这两个渲染函数,入参除了官网提到的参数外,还有两个参数dataindexs可以拿到,其中data对应该点位相应的dataOptions中的数据,可以通过给该数据添加自定义的属性来获取自己的设置的值。

实现效果及源码案例


源码:gitee源码示例

实现效果:

示例图片.png

示例图片2.png

参考链接:

renderjs | uni-app官网 (dcloud.net.cn)

海量点标记-覆盖物-教程-地图 JS API v2.0|高德地图API (amap.com)

点聚合-海量点标记-示例中心-JS API 2.0 示例 | 高德地图API (amap.com)