记一次在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>
renderjs script
标签中的module
对应需要绑定DOM的id
。- 绑定的数据为逻辑层中的数据,我这里绑定的是逻辑层中的
markers
,在markers
数据发生变化时,会主动触发绑定的视图层的更新函数。- 这里说明一下,
:markers="markers"
也可以写成任何:[key]="markers"
的形式,但是对应的触发函数的绑定也要改成对应的:change:[key]="[renderjs module].function"
形式。比如我这里可以改成:props="markers"
:change:props="amap.updateMarker"
,这样可以绑定多个数据。- 其他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>
- 加载方式参照高德地图给出的异步加载实例。
- 这里做了防止多次加载
JSAPI
的处理,但是我们挂载的加载完执行的onLoad
函数只会执行一次,所以不刷新的情况下再次打开地图,onLoad
函数不会再次触发,我们要通过判断条件去再次执行init
函数。- 因为renderjs视图层不支持vue的
beforeDestroy、destroyed
生命周期,所以清除地图相关数据放到mounted
生命周期去执行。- uniapp官方指出==H5 端逻辑层和视图层实际运行在同一个环境中,相当于使用 mixin 方式,可以直接访问逻辑层数据。==所以可以直接通过
this
去访问逻辑层中的数据。- 关于==先网络请求再操作地图的顺序==问题:我自己处理的办法是在数据更新后和地图加载完成后都去执行相关操作,但是需要添加前置判断条件,防止地图没有加载完成就去执行操作。
- 地图的尺寸问题:可以通过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();
})
}
});
});
- 创建点聚合的
MarkerCluster
函数需要三个参数,其中第二个参数dataOptions
我看到网上有传高德地图生成Marker
的数组,但是我试了试并不行,这里提一嘴。- 针对配置里的
renderClusterMarker
和renderMarker
这两个渲染函数,入参除了官网提到的参数外,还有两个参数data
和indexs
可以拿到,其中data
对应该点位相应的dataOptions
中的数据,可以通过给该数据添加自定义的属性来获取自己的设置的值。
实现效果及源码案例
源码:gitee源码示例
实现效果:
参考链接:
renderjs | uni-app官网 (dcloud.net.cn)