uniapp 接入高德地图 (Leaflet....)

参考链接
https://blog.csdn.net/qq_43067919/article/details/121032319
https://www.jianshu.com/p/57ebc0eef122
https://lbs.amap.com/api/jsapi-v2/summary
https://uniapp.dcloud.net.cn/tutorial/renderjs.html#renderjs

文章目录

  • 前言
  • 示例项目 [uniapp-gis-demo](https://gitee.com/duqingsong2002/uniapp-gis-demo.git)
  • 环境
  • 名称约定
  • 添加依赖
  • renderjs
  • 数据通信
    • 逻辑层访问renderjs
    • renderjs访问逻辑层
  • logo处理
  • 图片资源处理
    • 解决方案

前言

纯vue前端,零uniapp经验,需求让给uniapp 上的地图标记加个按钮,前人是用自带的Map组件实现的,用的高德地图,但是地图标记貌似不支持自定义啊,我寻思可能得自己实现了, 开始试了leaflet啊,没注意main.js 的css没导入成功(重新运行了才发现…),然后瓦片是错乱的, 而且接入高德地图也不方便(菜 … …兜兜转转发现高德有自带的sdk,使用效果很好啊

示例项目 uniapp-gis-demo

uniapp 接入高德地图 (Leaflet....)_第1张图片

环境

  • HBuilderX 3.4.18
  • Vue3

名称约定

常规的vue单文件组件如下

  • template: 视图层
  • script: 逻辑层
  • style: 样式层

添加依赖

可以使用npm安装 (个人推荐) ,也可以动态创建 script 方式引用

# npm 安装
npm i @amap/amap-jsapi-loader

renderjs

uniapp安卓端是没有BOM DOM这套的,所以依赖canvas相关的库是用不了,官方方案就是使用 renderjs
官方解释: 使用了非H5端不支持的API 小程序和App的js运行在jscore下而不是浏览器里,没有浏览器专用的js对象,比如document、xmlhttp、cookie、window、location、navigator、localstorage、websql、indexdb、webgl等对象。vue页面通过renderjs可以操作浏览器对象,进而可以让基于浏览器的库直接在uni-app的App端运行,诸如echart、threejs

举个简单栗子

key申请地址: https://console.amap.com/dev/key/app (登录控制台新建个应用就有了)

<template>
	<view id="a-map-container">
		
	</view>
</template>
<sctipt setup>
	....
</script>
<script module="AMap" lang="renderjs">
	import AMapLoader from '@amap/amap-jsapi-loader';
	
	AMapLoader.load({
	    "key": "68aae429918d9c1a46ba170e3xxxxx",              // 申请好的Web端开发者Key,首次调用 load 时必填
	    "version": "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
	    "plugins": [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
	}).then((AMap)=>{
	    new AMap.Map('a-map-container');
	})
	export default {
		// ...
		methods: {
			// ...
		}
	}
</script>
<style>
	#a-map-container {
		width: 100%;
		height: 100%;
	}
</style>

就是单文件组件后面加个script块,指定个 modulelang=“renderjs” 即可
如果不考虑数据交互的话module可以不指定值,反之需要指定个值用于外部访问

数据通信

参考资料

逻辑层访问renderjs

逻辑层是不能直接访问到renderjs的,视图层才能访问renderjs !!

视图层标签上有个update属性,可以监听逻辑层的数据变化再操作renderjs 以间接达到逻辑层访问renderjs的目的,这语法我没见过,我在其他vue3的项目试了下不行的啊,应该是uniapp支持的,不过具体文档我也没找见…

<template>

	<view id="a-map-container" :markers="tests" :change:markers="AMapInstance.reloadMarker">
		
	</view>
</template>
<script>
	import {ref} from 'vue'
	export default {
		setup(props) {
		
			const markers = ref() 
			setTimeout(() => {
				markers.value = []
			}, 10)
			return {
				markers 
			}
		
		}
	}
	
</script>
<script module="AMap" lang="renderjs">>
	export default {
		
		methods() {
			// ...
			reloadMarker(dataList) {
				console.log('reloadMarker', dataList);
			}
		},
	}
</script>

运行后控制台输出

reloadMarker, undefined
reloadMarker, [Object] []	

需要注意以下两点

  • :change 绑定的函数开始会调用一次,这次调用在vue3(setup语法糖,组合式API, 选项式API)情况下接收的非空参数会被转为JSON字符串并且前面会追加json://,另见https://ask.dcloud.net.cn/question/149521
    vue2经测试正常, 建议在vue3的情况下默认不要给值,比如ref()
const markers = ref() 
markers.value = []

注意: 这种情况也算有默认值了,所以也会导致接收的参数异常

  • 多次同步给值只生效最后一次, vue2和vue3都一样,例如:
const markers = ref() 
markers.value = 1
markers.value = 2
markers.value = 3

最后只会生效3,前几次都会被忽略掉

renderjs访问逻辑层

视图层标签上有个update属性,可以监听逻辑层的数据变化再操作renderjs 以间接达到逻辑层访问renderjs的目的,这语法我没见过,我在其他vue3的项目试了下不行的啊,应该是uniapp支持的,不过具体文档我也没找见…

<template>

	<view id="a-map-container" >
		
	</view>
</template>
<script>
	export default {
		setup(props) {
		
			const loaded = function(e) {
				console.log('加载成功了!!', e);
			}
			
			return {
				loaded
			}
		
		}
	}
	
</script>
<script module="AMap" lang="renderjs">>
	export default {
		
		mounted() {
			// ...
			this.$ownerInstance.callMethod('loaded', 8888)
		},
	}
</script>

运行后即可看到 加载成功了!!, [Number] 8888
需要注意以下两点

  • $ownerInstance 需要执行到mounted时才会存在:update 初次调用renderjs函数时机在mounted之前,所以直接在被访问的methods函数里访问逻辑层很可能直接报错的
  • $ownerInstance.callMethod 访问的函数使用setup语法糖时无法访问到, 如果需要在renderjs访问逻辑层的话不要使用setup语法糖 (后续官方可能也会支持的)

logo处理

直接css隐藏

>>> .amap-logo,
>>> .amap-copyright {
	display: none !important;
}

我是直接在组件样式层加的,不加深度选择器 样式不生效不知道为啥,写到外面可以不加 忙猜…算了不盲猜了

图片资源处理

安卓端添加Marker时,或者自定义Marker设置图片时,图片会加载失败
下面这段代码在手机上就看不到默认的图标

new AMap.Marker({
    position: new AMap.LngLat(116.39, 39.9),   // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
    title: '北京'
})

解决方案

  • 转base64使用

Leaflet等差不多,但要注意一点,css不能在main.js引用
在这里插入图片描述

你可能感兴趣的:(vue.js,前端,javascript)