首页 前端知识 基于高德JSAPI的H5选址组件

基于高德JSAPI的H5选址组件

2024-04-29 12:04:57 前端知识 前端哥 946 184 我要收藏

基于高德JSAPI的H5选址组件

一、需求

  • 可以切换城市
  • 可以检索城市下的地址
  • 拖拽地图选点
  • 显示选点附件的poi
  • 双指缩放时以地图的中心点为中心

二、效果如图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、准备

成为开发者并创建 key,为了正常调用 API ,请先注册成为高德开放平台开发者,并申请 web 平台(JS API)的 key 和安全密钥,点击 具体操作。

2021年12月02日后创建的 key 必须配备安全密钥一起使用,具体用法参见JS API 安全密钥使用

四、开发

初始化

<template>
	<view id="container"></view>
	<view class="result-list footer">
		<van-list :finished="finished">
			<van-cell v-for="(item, index) in resultList" :key="index" center :title="item.name" :label="item.address"
				@click="handleClickAddress(item)">
				<template #extra>
					<span class="map-distance">{{ handleDistance(item.distance) }}</span>
				</template>
			</van-cell>
		</van-list>
	</view>
</template>
initMap() {
            // 初始化地图
            const _this = this
            let map = null;
            positionPicker = null;
            AMapLoader.load({
                "key": "您的key",              // 申请好的Web端开发者Key,首次调用 load 时必填
                "version": "2.0",       // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                "plugins": [
                    'AMap.Geolocation', // 定位插件
                    'AMap.AutoComplete', // 输入提示与POI搜索
                    'AMap.ToolBar', // 缩放工具条
                    'AMap.Scale', // 比例尺插件
                ],
                "Loca": {                // 是否加载 Loca, 缺省不加载
                    "version": '2.0.0'  // Loca 版本,缺省 1.3.2
                },
            }).then(async (AMap) => {
                await this.asyncLoadAmapUI()
                map = new AMap.Map('container', {
                    zoom: 18,
                    scrollWheel: true,
                    // viewMode: '3D', // 3D 模式视图,
                    // mapStyle: 'amap://styles/macaron', // 地图样式设置
                })
                window.map = map
                AMapUI.loadUI([
                    'misc/MobiCityPicker',
                ], (
                    MobiCityPicker,
                ) => {
                    this.handleCityPicker(MobiCityPicker, map)
                });
                const geolocation = new AMap.Geolocation({
                    // 是否使用高精度定位,默认:true
                    enableHighAccuracy: true,
                    // 设置定位超时时间,默认:无穷大
                    timeout: 6000,
                    position: 'RB',
                    showButton: true,
                    panToLocation: true,
                    zoomToAccuracy: true
                })
                map.addControl(geolocation);
                const scale = new AMap.Scale();
				map.addControl(scale);
				// 有初始值, 逆向地理编码查询地理位置详细信息
				// 没有初始值,进行GPS定位查询
	})
 },
 handleCityPicker() {
 	// 处理点击左上角切换城市
 	this.cityPicker = new MobiCityPicker({
		//设置主题(同名的className会被添加到外层容器上)
		theme: "light"
	});
	//监听城市选中事件
	this.cityPicker.on("citySelected", (cityInfo) => {
		this.cityPicker.hideImmediately();  //立即隐藏
		console.log(cityInfo);        //选中的城市信息
		const { adcode, name, lat, lng } = cityInfo
		this.curCityName = name
		this.curCityCode = adcode
		// map.setCenter([lng, lat])
	});
 },
 handlePositionPicker(map, PositionPicker, SimpleInfoWindow) {
			positionPicker = new PositionPicker({
				mode: 'dragMap',// 设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'
				// dragMap模式,通过拖动地图来选择需要的点。marker一直位于地图的中心点
				// dragMarker模式,通过拖动marker来选择需要的点
				map: map, // 依赖地图对象
				iconStyle: { //自定义外观
					url: '//webapi.amap.com/ui/1.0/assets/position-picker2.png',
					ancher: [24, 40],
					size: [40, 40]
				}
			});
			if (this.point.lng) {
				// 初始化positionPicker
				positionPicker.start([this.point.lng, this.point.lat]);
			}
			// 选址结束后的回调函数
			positionPicker.on('success', res => {
				// 拖动地图后,选点成功回调
			})
			positionPicker.on('fail', res => {
				// 拖动地图后,选点失败回调
			})
		},
		handleSearchValueChange(val) {
			// 搜索事件处理
			// 主要逻辑
			const autoComplete = new AMap.Autocomplete({
				city: this.curCityName,
				citylimit: true
			});
			autoComplete.search(val, (status, result) => {
				// 搜索成功时,result即是对应的匹配数据
				let resAddress = [];
				if (status == 'complete') {
					// 检索的结果
					console.log(result.tips);
				}
			})
		}

五、问题

https

地图要使用点击定位到当前位置,必须是https协议。
1. https+IP
chrome https+IP时,需要翻墙才能定位到当前位置,firefox和edge不需要翻墙也可以直接定位到当前。
2. https+域名
无需其他任何操作,生产一定要使用https+域名

安全密钥

2021年12月02日以后申请的key需要配合您的安全密钥一起使用。也就是说2021年12月02日以后申请到key由一对组成,一个时key,一个是安全密钥。

注意:
1. 您这个设置必须是在JS API 脚本加载之前进行设置,否则设置无效。
2. 将key和安全密钥都写在前端代码中是很不安全的,生产需要将安全密钥配置到nginx。
具体如何配置请参考[JS API 安全密钥使用](https://lbs.amap.com/api/javascript-api-v2/guide/abc/jscode)。
3. 如果开发测试是http协议,需要转发到https对应的端口,或者直接使用https的端口。
4. 如果https的证书是自签的,在浏览器中打开。需要手动信任这个证书一次,否则会报net::ERR_CERT_COMMON_NAME_INVALID的错误
5. 如果https的证书是自签的,在APP 的webview中打开,需要APP配置一下白名单。

中心点缩放

双指缩放的时候,本来想要的目标点位于地图中心,可是一缩放,目标点就跑了,不位于地图中心了。

那能想到的方法就是,监听地图缩放事件,通过setCenter,把中心位置重新设置成目标点。但是bug一大把,缩放的时候,地图会莫名其妙的滑动很长的距离。

之后还是通过查看API发现了方法,由此骂自己千百遍,叫你不看API!!!只知道面向百度(现在变成了面向chatgpt,但是问不对要点也没有太大用处)开发。

map = new AMap.Map('container', {
	zoom: 18,
	scrollWheel: true,
	touchZoomCenter: 1, // 可缺省,当touchZoomCenter=1的时候,手机端双指缩放的以地图中心为中心,否则默认以双指中间点为中心
})

touchZoomCenter这个属性,针对移动端,为1的时候,双指缩放会以地图的中心为中心进行缩放。这样就保证了缩放的时候位于中心的目标点不会跑。

还有个奇怪的问题:在我集成的app的webveiw中,当地图放大到比例尺小于等于1:25级以上(具体多少zoom值没有看,18以上吧)时,地图的瓦片就加载不出来了。微信中打开地图页面的链接时,放到到最大1:10时展示也是正常的。

最后,再重申一下,一定要看API,不要拿来就用,就百度。

参考
1. JS API 安全密钥使用
2. 高德地图 JS API 2.0教程
3.Geolocation.getCurrentPosition

转载请注明出处或者链接地址:https://www.qianduange.cn//article/6618.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!