vue3 +百度地图 实现 地点检索,输入联想,经纬度,逆地理编码,创建标记,label等

由于百度地图文档确实有点欠缺,在这里记录一下

vue3 + 百度地图(js api 3.0)

  • 需求: 地图弹框组件,可以搜索地图点,输入联想,回车定位等
  • 项目:vue3 + ts + 百度地图js api

实现效果如下

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

实现方式

  • 首先引入百度地图
const loadingBMPGL = (ak: string) => {
	return new Promise(function (resolve, reject) {
		window.init = () => resolve(BMapGL);
		const script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = `https://api.map.baidu.com/api?v=3.0&type=webgl&ak=${ak}&callback=init`;
		script.onerror = reject;
		document.head.appendChild(script);
	});
};
  • 初始化地图实例并监听事件
const initMap = (val: any) => {
	loadingBMPGL(val).then((BMapGL: any) => {
		map = new window.BMapGL.Map('mapContainer');
		// 初始化地图,设置中心点坐标和地图级别
		var ac = new window.BMapGL.Autocomplete({
			//建立一个自动完成的对象
			input: 'searchInput',
			location: map,
		});
		ac.setInputValue(searchData.value);
		ac.addEventListener('onhighlight', function (e) {
			var str = '';
			var value = e.fromitem.value;
			if (e.fromitem.index > -1) {
				str =
					value.province +
					' ' +
					value.city +
					' ' +
					value.district +
					' ' +
					value.street +
					' ' +
					value.business;
			}
			var highlight = 'Suggestion: ' + str;
			document.getElementById('searchInput').placeholder = str;
		});
		ac.addEventListener('onconfirm', function (e) {
			var confirmStr =
				e.item.value.province +
				'/' +
				e.item.value.city +
				'/' +
				e.item.value.district +
				'/' +
				e.item.value.street +
				'/' +
				e.item.value.business;
			const address = {
				name: e.item.value.address,
				address: confirmStr,
				point: e.item.value.location,
			};
			selectResult(address);
			console.log('确认选择: ', e, confirmStr);
		});
		// 以天安门为例
		map.centerAndZoom(new window.BMapGL.Point(116.404, 39.915), 11);
		// 启用地图拖拽事件
		map.enableDragging();
		// 启用地图缩放
		map.enableScrollWheelZoom(true);
		// 监听地图点击事件
		map.addEventListener('click', function (e) {
			// 获取点击位置的坐标
			const point = e.latlng;
			// 清除之前的标记
			if (currentMarker) {
				map.removeOverlay(currentMarker);
			}
			map.clearOverlays();
			// 创建标记并添加到地图上
			currentMarker = new window.BMapGL.Marker(point);
			map.addOverlay(currentMarker);
			map.centerAndZoom(point, 35);
			// geolocation.enableSDKLocation();
			// 创建地理编码服务实例
			const geocoder = new window.BMapGL.Geocoder();
			// 使用地理编码服务获取地址
			geocoder.getLocation(point, function (result) {
				if (result) {
					const address = result.content.address + result.content.poi_desc;
					searchData.value = address;
					lat.value = point.lat;
					lng.value = point.lng;
					// 在点击位置显示信息窗口
					const infoWindow = new window.BMapGL.Label(
						'您点击的位置:' + address + '<br>' + '经纬度:' + point.lng + ',  ' + point.lat
					);
					infoWindow.setStyle({
						color: 'black',
						fontSize: '14px',
						backgroundColor: 'white',
						border: '1px solid #ccc',
						padding: '2px',
					});
					currentMarker.setLabel(infoWindow);
				} else {
					console.log('未找到该位置的地址');
				}
			});
		});
		// 0: 成功。表示搜索请求成功,并且结果可以通过 result 对象进行获取和处理。
		// 1: 没有找到匹配的结果。表示搜索关键字没有匹配到任何地点。
		// 2: 请求被拒绝。可能是由于权限问题或请求格式不正确。
		// 3: API 密钥无效。表示使用的 API 密钥不正确或已过期。
		// 4: 发生了未知错误。表示出现了无法预料的问题。

		localSearch.value = new window.BMapGL.LocalSearch(map, {
			// renderOptions: { map: map },
			onSearchComplete: function (result) {
				if (localSearch.value.getStatus() === 0) {
					if (result._pois.length != 0) {
						console.log('Search completed:', localSearch.value, result);
						searchResults.value = result._pois.map(poi => {
							return {
								id: poi.uid,
								name: poi.title,
								address: poi.address,
								point: poi.point,
							};
						});
					}
				} else {
					console.log('Search failed:', result, localSearch.value.getStatus());
				}
			},
		});
		// 初始化搜索一次
		// searchLocation(searchData.value);
	});
};

其实这里有两种方式实现;

  1. 其一是使用BMapGL.Autocomplete 创建一个自定义对象,需要一个input框来绑定输入框,还有一个地图的区域
<div class="map-container" id="mapContainer" ref="mapContainer"></div>
			<div class="search-box">
				<el-input
					id="searchInput"
					ref="searchdom"
					style="width: 250px"
					v-model="searchData"
					placeholder="搜索地点"
				>
					<!-- @input="searchLocation" -->
					<template #suffix>
						<img class="search-icon" src="@/assets/img/water-works/search.png" alt="" />
					</template>
				</el-input>
				<!-- 显示搜索结果列表 -->
				<!-- <div class="search-list" v-if="searchResults.length">
					<ul>
						<li v-for="result in searchResults" :key="result.id" @click="selectResult(result)">
							<span style="padding: 12px 7px"> {{ result.name }}</span>
						</li>
					</ul>
				</div> -->
			</div>

这里需要注意的是:需要单独设置一下搜索结果列表的层级,不然会遮挡导致看不见,要去掉style标签的 scoped,这样的话重写的css样式才能生效。

.tangram-suggestion {
	z-index: 99999;
}

onhighlightonconfirm 分别设置监听输入联想和选择搜索结果的事件,可以在回调中设置需要的操作

  1. 第二种就是利用BMapGL.LocalSearch 方法,也就是localSearch.value
在输入框上设置  `@input="searchLocation"`
const searchLocation = (keyword: any) => {
	localSearch.value.search(keyword);
};
调用BMapGL.LocalSearch 的回调方法 给searchResults.value 赋值然后将上面的搜索列表注释放开就可以在选中事件中做相应操作,如:
const selectResult = (result: any) => {
	console.log(result);
	// 清空搜索结果列表
	searchResults.value = [];
	// 清空搜索框
	searchData.value = result.address;
	// 获取搜索结果
	const poi = result.point;
	// 在地图上标记位置
	markerPosition.value = poi;
	lat.value = poi.lat;
	lng.value = poi.lng;
	// const icon = new window.BMapGL.Icon('@/assets/img/water-works/marker.svg', new window.BMapGL.Size(20, 20));
	// icon.setImageSize(new window.BMapGL.Size(32,32));
	// const marker = new window.BMapGL.Marker(poi,{ icon: icon });
	const marker = new window.BMapGL.Marker(poi);
	// 创建标签
	const label = new window.BMapGL.Label(
		'名称:' + result.name + '<br>' + '经纬度:' + poi.lng + ',  ' + poi.lat,
		{
			offset: new window.BMapGL.Size(20, -10), // 调整标签位置
		}
	);
	label.setStyle({
		color: 'black',
		fontSize: '14px',
		backgroundColor: 'white',
		border: '1px solid #ccc',
		padding: '2px',
	});
	// 将标签添加到标记
	marker.setLabel(label);
	map.addOverlay(marker);
	map.centerAndZoom(poi, 35);
};

注意事项

  1. vue3 和ts项目中没有直接的BMapGL 对象,所以挂在了Window下面
  2. 注意修改结果列表的层级z-index
Vue3 和百度地图结合可以方便地实现实时定位和点击事件下的信息展示。以下是简单的步骤和原理: 1. **定位(Geolocation)**: - 首先,在项目中引入 Vue3 和百度地图 JavaScript API。 - 使用 `@vue/cli-plugin-babel` 或者其他插件支持 ES6 模块导入。 - 在组件内通过 `this.$axios` 或者其他网络请求库获取用户的地理位置数据,如经纬度。 ```javascript import BMap from '@bmap/web'; setup() { const geolocation = new BMap.Geolocation(); geolocation.getCurrentPosition((res) => { // res.accuracy 返回精度,坐标在res.center中 console.log(res); // 更新地图中心点到用户位置 this.map.setCenter(res.center); }, (err) => { console.error('无法获取位置', err); }); } ``` 2. **点击点展示信息**: - 创建一个虚拟地图标记(Marker)表示地图上的兴趣点,每个标记对应一个信息对象。 - 当用户点击标记时,绑定点击事件监听器,显示对应的数据显示组件(例如一个 Popover 或者模态框)。 ```javascript const markerOptions = { position: // 标记位置, draggable: false, click(e) { this.showInfoWindow(e); // 显示信息窗口 }, }; methods: { showInfoWindow(e) { // e.point 获取鼠标点击的具体坐标 const infoContent = `<div>${this.markers[e.point.lnglat].info}</div>`; // 假设markers是一个包含经纬度及对应信息的对象数组 const infowindow = new BMap.InfoWindow(infoContent, { offset: new BMap.Size(0, -40) }); // 设置信息窗体样式 infowindow.open(this.map, e.point); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值