uniapp使用renderjs引入天地图实现地图选点以及搜索附近poi点

APP自定义地图选点,可换底图,可换图标,可自定义样式。

要实现下面设计图需求,但要求地图底图是天地图,使用了renderjs进行引入。

不罗嗦,下边是具体实现步骤

一、跳转

由于业务需求,需要点击图标进行地图选点的跳转(若需求只需选点,可用高德地图的地图选点,只需几行代码即可,高德地图有现成的)

点击跳转,选完之后带入地址。

            // 点击勘测地址
			surveyAddressBtn() {
				console.log('打开地图');
				// 天地图地图选点leaflet
				uni.navigateTo({
					url: '/pages/project/choicePointPage'
				})
				// 高德地图的选点 不支持无网
				// uni.chooseLocation({ geocode: true, su***ess: (res) => { this.surveyData.surveyAddress = res.address } })
			},

ps:高德地图选点使用直接跳转即可

// 高德地图的选点 不支持无网
 uni.chooseLocation({ geocode: true, su***ess: (res) => { this.surveyData.surveyAddress = res.address } })

二、地图选点页面

choicePointPage.vue

<template>
	<!-- 选择点位天地图 -->
	<view class="map-page-wrapper">
		<view class="map-box">
			<jLeaflet ref="map" :map-key="mapKey" :lonlat="lonlat" :zoom="zoom" :show-center-icon="showCenterIcon" :center-icon="centerIcon" :show-location-icon="showLocationIcon" :on-location="location" :on-loaded="loaded" :on-start-drag="startDrag" :on-zoom-end="zoomEnd" :on-end-drag="endDrag"
				:zoomMapT="zoomMapT" @calolBack="calolBack" />
		</view>
		<view class="tool-box">
			<view class="topBox">
				<u-icon name="arrow-left" color="#ffffff" size="22" @click="backBtn"></u-icon>
				<view>
					<u-button type="primary" @click="choiceAddressBtn" customStyle="{width: 60rpx;height: 60rpx;}" color="#5f8dfe" text="确定"></u-button>
				</view>
			</view>
			<!-- <view class="tool" @tap="look()">查看</view> -->
		</view>
		<u-popup :show="true" :overlay="false" round='10'>
			<view class="upopupAddress">
				<u-search placeholder="搜索地点" inputAlign="center" @search="ssearch" v-model="keyword" :showAction="false"></u-search>
				<view style="height: 45vh;overflow: auto;" v-show="!uLoading">
					<view class="singlePio" v-for="item,index in poiList" :key="index">
						<view class="poiItem" @click="choiceItemBtn(poiList,item)">
							<view class="title">{{item.name}}</view>
							<view class="contents">
								<view class="distance">{{item.roadDistince}}</view>
								<view class="address">{{item.address}}</view>
							</view>
						</view>
						<view class="choice" v-show="item.isChoice">
							<u-icon name="checkmark" color="#7fa3fe" size="22"></u-icon>
						</view>
					</view>
				</view>
				<view v-show="uLoading" style="margin-top: 40rpx;">
					<u-loading-icon></u-loading-icon>
				</view>
			</view>
		</u-popup>
	</view>
</template>
<script>
	import jLeaflet from './***ponents/jLeaflet/jLeaflet.vue'
	// 导入本地图标
	import Vector from '@/static/mapImg/Vector.png';
	import point from '@/static/mapImg/point.png';
	import dqwz from '@/static/mapImg/dqwz.png';
	import { getSearchBounds } from '@/utils/SearchRangePoint.js' //地理空间搜索范围计算函数
	export default {
		***ponents: {
			jLeaflet
		},
		data() {
			return {
				// 天地图官网地址 https://oauth.tianditu.gov.***/
				mapKey: "输入你的天地图key",
			

				// 中心位置
				lonlat: [39.89945, 116.40769], // 故宫
				// lonlat: [],
				// 缩放
				zoom: 16,
				// 地图展示类型
				type: 0,
				// 显示中心图标
				showCenterIcon: true,
				// 显示定位图标
				showLocationIcon: false,
				// 不设置使用默认图标
				centerIcon: "",
				zoomMapT: 0,
				// 用户当前位置
				userLocation: {
					lon: 110.40769,
					lat: 32.89945,
					altitude: 0, // 海拔
					address: '',
				},
				keyword: '', // 搜索关键字
				inputFocus: false, // input输入框焦点状态
				poiList: [], // poi点列表
				// 选中的poi点
				choicePoi: {
					address: '', // 此点的具体信息(分类)
					name: '', // 此点最近地点信息
					roadDistince: '', //此点距离此路的距离		
				},
				uLoading: false, // 拖拽loading

			};
		},
		async onLoad() {
			// 获取当前用户位置
			await this.getLocation();
			console.log('先获取位置', this.lonlat);
		},
		mounted() {
			console.log('再绑定组件', this.lonlat);
			// 绑定组件
			this.map = this.$refs.map;
		},
		methods: {
			// 返回
			backBtn() {
				uni.navigateBack();
			},
			// 搜索
			ssearch() {
				this.searchPoi('2')
			},

			// 确定按钮
			choiceAddressBtn() {
				uni.$emit('choiceAddressPoi', this.choicePoi)
				this.backBtn()
			},
			// 获取当前用户位置
			async getLocation() {
				const that = this;
				console.log('进入获取当前用户位置');
				await uni.get***workType({
					su***ess: async function(res) {
						console.log('获取网络状态', res.***workType);
						if (res.***workType === 'none') {
							await plus.geolocation.getCurrentPosition(su***essCB => {
								console.log('系统--获取当前用户位置--无网', su***essCB);
								that.userLocation.lon = su***essCB.coords.longitude;
								that.userLocation.lat = su***essCB.coords.latitude;
								that.userLocation.altitude = su***essCB.coords.altitude;
								that.lonlat[0] = res.longitude
								that.lonlat[1] = res.latitude
							}, errorCB => {
								console.log('系统--获取当前用户位置失败--无网', errorCB);
							}, {
								provider: 'system',
								coordsType: 'wgs84',
								// coordsType: 'gcj02',
								// enableHighA***uracy: true, //是否高精确度获取位置信息
								// timeout: 10000, //  获取位置信息的超时时间
								// maximumAge: 0, // 获取位置信息的间隔时间
								geocode: true // 是否解析地址信息
							})
						} else {
							await uni.getLocation({
								// geocode: true,
								// type: 'gcj02',
								// altitude: true, 
								// isHighA***uracy: true,
								// highA***uracyExpireTime: 30000,
								su***ess: function(res) {
									console.log('uni-获取当前用户位置--有网', res);
									that.userLocation.lon = res.longitude;
									that.userLocation.lat = res.latitude;
									console.log('222');
									that.userLocation.altitude = res.altitude;
									console.log('333');
									that.lonlat[0] = that.userLocation.lon;
									console.log('444');
									that.lonlat[1] = that.userLocation.lat;
									console.log('5555');
									console.log('that.userLocation用户信息', that.userLocation);
								},
								fail: function(res) {
									console.log('uni-获取当前用户位置失败--有网', res);
								}
							});
						}
					}
				});

			},
			look() {
				console.log('点击查看');
				// console.log('地图页面this.map.look()', this.map.look());
				this.map.look()
			},
			calolBack(val) {
				console.log('calolBack', val);
				// this.zoomMapT = val.zzz
			},
			location() {
				console.log("点击定位按钮回调");
				this.map.resize()
			},
			// 天地图逆地理解析
			getAddress(data) {
				uni.request({
					url: `http://api.tianditu.gov.***/geocoder?postStr={ 'lon':${data.lonlat[0]}, 'lat': ${data.lonlat[1]}, 'ver':${ 1} }&type=geocode&tk=${this.mapKey}`, //天地图逆地理解析接口
					su***ess: (res) => {
						console.log('天地图逆地理解析res.data', res.data);
						const obj = {
							address: res.data.result.formatted_address,
							name: res.data.result.address***ponent.address,
							hotPointID: "1", // 热点id
							location: res.data.result.location,
							lonlat: `${res.data.result.location.lon},${res.data.result.location.lat}`, // 经纬度 x,y
							isChoice: true // 是否选中
						}
						this.poiList = [obj]
						this.choicePoi = obj
						this.searchPoi('1', obj)
					}
				});
			},
			// 点击勾选poi点
			choiceItemBtn(list, item) {
				// 选中item的isChoice为true
				item.isChoice = true
				// 其他item的isChoice为false
				list.forEach(item2 => {
					if (item2.hotPointID !== item.hotPointID) {
						item2.isChoice = false
					}
				})
				this.choicePoi = item
				this.poiList = list
				console.log('点击勾选poiList', this.poiList);
				console.log('点击勾选choicePoi', this.choicePoi);
				const lonlat = item.lonlat.split(',')
				this.map.setCenter(lonlat[0], lonlat[1])
			},
			// 天地图搜索附近poi点信息
			searchPoi(type, data) {
				// type 移动地图搜索 1   输入框搜索 2
				let seaechVal = ''
				let option = {}
				if (type === '1') {
					seaechVal = data.address
					option = {
						latitude: +data.location.lat, // 纬度
						longitude: +data.location.lon, // 经度
						distance: 100 // 范围 100公里
					}
				} else {
					option = {
						latitude: +this.lonlat[1], // 纬度
						longitude: +this.lonlat[0], // 经度
						distance: 100 // 范围 100公里
					}
					seaechVal = this.keyword
				}

				const pointRange = getSearchBounds(option)
				const entents = pointRange.minLon + ',' + pointRange.minLat + ',' + pointRange.maxLon + ',' + pointRange.minLat
				const start = 1
				const url = `http://api.tianditu.gov.***/v2/search?postStr={"keyWord":"${seaechVal}","level":"${this.zoom}","mapBound":"${entents}","queryType":1,"start":4,"count":10}&type=query&tk=${this.mapKey}`
				console.log('url', url);
				uni.request({
					url: url, //天地图搜索附近poi点信息接口
					su***ess: (res) => {
						this.uLoading = false
						console.log('天地图搜索附近poi点信息res.data', res.data);
						if (+res.data.count > 0 && type === '1') {
							this.poiList = [...this.poiList, ...res.data.pois];
						} else {
							this.poiList = res.data.pois;
							// 移动到第一个点
							const lonlat = this.poiList[0].lonlat.split(',')
							this.map.setCenter(lonlat[0], lonlat[1])
						}
						this.poiList.forEach(item => {
							this.$set(item, 'isChoice', false)
							// 计算最新两点之间的距离
							const lonlat = item.lonlat.split(',')
							let distance = this.calculateDistanceBackup(
								this.lonlat[1],
								this.lonlat[0],
								lonlat[1],
								lonlat[0],
							)
							if (distance > 1000) {
								distance = (distance / 1000).toFixed(2) + 'km'
							} else {
								distance = distance + 'm'
							}
							this.$set(item, 'roadDistince', distance)
							// 若distance单位为m且小于100m则显示为100m内
							if (distance.includes('m') && distance.replace('m', '') < 100) {
								this.$set(item, 'roadDistince', '100m内')
							}
						})
						this.poiList[0].isChoice = true
						this.choicePoi = this.poiList[0]
					}
				});
			},
			// 根据定位坐标与传入坐标计算距离
			calculateDistanceBackup(lat1, lng1, lat2, lng2) {
				// const R = 6371000 // 地球半径,单位米 
				const R = 6378137 // 赤道半径,单位米 
				const dLat = this.toRad(lat2 - lat1)
				const dLon = this.toRad(lng2 - lng1)
				const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
					Math.cos(this.toRad(lat1)) * Math.cos(this.toRad(lat2)) *
					Math.sin(dLon / 2) * Math.sin(dLon / 2)
				const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))

				return Math.round(R * c)
			},
			// 将角度转换为弧度
			toRad(degree) {
				return degree * Math.PI / 180
			},

			// 地图创建完成
			loaded(data) {
				console.log("地图创建完成", data);
				this.getAddress(data) // 天地图逆地理解析
			},
			// 地图缩放完成
			zoomEnd(lon, lat) {
				console.log("地图缩放完成", lon, lat);
			},
			// 开始拖拽
			startDrag(lon, lat) {
				this.uLoading = true
				console.log("开始地图拖拽", lon, lat);
			},
			// 结束拖拽
			endDrag(lon, lat) {
				const data = {
					lonlat: [lon, lat]
				}
				this.getAddress(data) // 天地图逆地理解析
				console.log("结束地图拖拽", lon, lat);
			},
			setZoom(zoom) {
				this.zoom += zoom;
				if (this.zoom <= 10) this.zoom = 1;
				if (this.zoom >= 20) this.zoom = 20;
				this.map.setZoom(this.zoom);
			},
			setType(type) {
				// type 0矢量地图 1卫星地图 其他矢量地图
				this.type = type;
				this.map.setType(this.type);
			},
			setCenter(lon, lat) {
				this.lonlat = [lon, lat];
				this.map.setCenter(lon, lat);
			},
			setIcon() {
				// 默认图标和icon切换显示
				this.centerIcon = this.centerIcon ? "" : Vector;
			},
		}
	};
</script>

<style scoped lang="scss">
	.map-page-wrapper {
		width: 100%;
		height: 100vh;

		.map-box {
			width: 100%;
			height: 100%;
		}

		.tool-box {
			position: absolute;
			// 天地图默认z-index:400 需要大于400
			z-index: 999;
			top: 80rpx;
			left: 20rpx;
			width: 100%;
			border-radius: 8rpx;
			padding: 16rpx;
			// display: flex;
			// flex-wrap: wrap;
			// gap: 16rpx;

			.topBox {
				display: flex;
				justify-content: space-between;
				width: 90%;
			}

			.tool {
				font-size: 28rpx;
				border-radius: 8rpx;
				padding: 12rpx 24rpx;
				background: #FFFFFF;
				box-shadow: 0 0 6rpx rgba(0, 0, 0, .15);
			}

		}

		.upopupAddress {
			height: 50vh;
			padding: 40rpx 20rpx;

			.singlePio {
				display: flex;
				justify-content: space-between;
				align-items: center;
				padding: 20rpx;

				.poiItem {

					.title {
						margin: 10rpx 0;
					}

					.contents {
						display: flex;
						justify-content: left;
						align-items: center;
						font-size: 25rpx;
						color: #c6c6c6;

						.distance {
							// padding-right: 10rpx;
							margin-right: 10rpx;
							border-right: solid;
							border-right-width: 1rpx;
							border-right-color: #c6c6c6;
							width: 100rpx;
						}

						.address {
							width: 500rpx;
						}
					}
				}

				.choice {}
			}
		}
	}
</style>

三、renderjs组件实现地图操作

        jLeaflet.vue

<template>
	<view class="ly-map-wrapper">
		<!-- 地图展示 -->
		<view :id="mapId" :config="config" :change:config="LyMap.init" :call="option" :change:call="LyMap.call" class="ly-map" />
		<!-- 中心图标 -->
		<image v-if="showCenterIcon" :src="centerIcon||defCenterIcon" class="ly-center-icon" />
		<!-- 定位图标 -->
		<view v-if="showLocationIcon" class="ly-location-icon" @click="onLocation">
			<image :src="locationIcon" class="icon" />
		</view>
	</view>
</template>

<script>
	import centerIcon from '@/static/mapImg/point.png';
	import locationIcon from '@/static/mapImg/dw.png';
	export default {
		// 接口参数
		props: {
			// 地图key
			mapKey: {
				type: String,
				default: ''
			},
			// 经纬度
			lonlat: {
				type: Array,
				default: () => ([111.668097, 40.825417]),
			},
			// 缩放
			zoom: {
				type: Number,
				default: 13,
			},
			// 是否显示中心定位图标
			showCenterIcon: {
				type: Boolean,
				default: false,
			},
			// 中心点图标
			centerIcon: {
				type: String,
				default: "",
			},
			// 是否显示用户定位图标
			showLocationIcon: {
				type: Boolean,
				default: false,
			},
			// 点击地图定位按钮
			onLocation: {
				type: Function,
				default: () => {}
			},
			// 地图加载完成回调
			onLoaded: {
				type: Function,
				default: () => {}
			},
			// 地图点击事件
			onTouchstart: {
				type: Function,
				default: () => {}
			},
			// 地图做拽开始
			onStartDrag: {
				type: Function,
				default: () => {}
			},
			// 地图做拽结束
			onEndDrag: {
				type: Function,
				default: () => {}
			},
			// 地图缩放结束
			onZoomEnd: {
				type: Function,
				default: () => {}
			},
			// 测试级别
			zoomMapT: {
				type: Number,
				default: 0
			}
		},
		// 数据定义
		data() {
			return {
				// 地图容器id
				mapId: this.genId(),
				// 调用渲染层
				option: {},
				// 地图配置(传递到render中的数据)
				config: {},
				// 调用渲染层队列
				event: [],
				// 事件处理定时器
				timer: null,
				// 中心图标
				defCenterIcon: centerIcon,
				// 定位图标
				locationIcon: locationIcon,
			}
		},
		// 挂载完成后
		mounted() {
			// 设置渲染数据
			this.config = {
				mapId: this.mapId,
				mapKey: this.mapKey,
				lonlat: this.lonlat,
				zoom: this.zoom,
				// TDT_API,
			};
		},
		// 通用方法
		methods: {
			// 生成唯一ID
			genId() {
				let result = '';
				const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
				const charactersLength = characters.length;
				for (let i = 0; i < 30; i++) {
					result += characters.charAt(Math.floor(Math.random() * charactersLength));
				}
				return Date.now() + result;
			},
			// 调用
			call() {
				if (this.timer) return;
				// 消费事件队列(生产者/消费者机制)
				this.timer = setInterval(() => {
					if (this.event.length) {
						this.option = this.event.shift();
					} else {
						clearInterval(this.timer);
						this.timer = null;
					}
				}, 10);
			},
			// 添加事件队列
			addEvent(name, data) {
				// #ifdef APP
				// tips:由于采用监听option改变来调用方法,
				// 如果连续变化两次option,渲染层只会则监不到最后一次
				// 导致调用丢失,所以采用事件队列形式解决,稍微延时10ms
				// 等待渲染进程监听到option变化,在进行更改option
				// 从性能上,几乎无感可以放心使用
				const option = {
					id: this.genId(),
					name: `_${name}`,
					data
				};
				this.event.push(option);
				this.call();
				// #endif

				// #ifndef APP
				this[`_${name}`] && this[`_${name}`](data);
				// #endif
			},
			// 获取当前地图层级
			look() {
				this.addEvent("look");
			},
			// 回调
			getZoomCallback(item) {
				console.log('// 回调', item);
				this.$emit('calolBack', item)
			},
			// 设置
			setOption(option) {
				this.addEvent("setOption", option);
			},
			// 设置位置
			setCenter(lon, lat, zoom) {
				this.addEvent("setCenter", {
					lon,
					lat,
					zoom
				});
			},
			// 设置类型 0矢量地图 1卫星地图
			setType(type) {
				this.addEvent("setType", {
					type
				});
			},
			// 设置标注 marks:[{url, width, height, lon, lat}]
			setMarkers(markers = []) {
				this.addEvent("setMarkers", {
					markers
				});
			},
			// 设置缩放
			setZoom(zoom) {
				this.addEvent("setZoom", {
					zoom
				});
			},
			// 重置地图
			resize() {
				this.addEvent("resize");
			},
			// 地图加载完成
			onMapLoad(data) {
				this.onLoaded && this.onLoaded(data);
			},
			// 点击地图定位按钮
			onMapLocation() {
				this.onLocation && this.onLocation();
			},
			// // 点击地图
			// onTouchstart() {
			// 	this.touchstart && this.touchstart();
			// 	this.touchstart()
			// },
			// 开始拖拽地图
			onMapStartDrag(pos) {
				this.onStartDrag && this.onStartDrag(Number(pos.lon).toFixed(6), Number(pos.lat).toFixed(6));
			},
			// 结束拖拽地图
			onMapEndDrag(pos) {
				this.onEndDrag && this.onEndDrag(Number(pos.lon).toFixed(6), Number(pos.lat).toFixed(6));
			},
			// 结束缩放地图
			onMapZoomEnd(pos) {
				this.onZoomEnd && this.onZoomEnd(Number(pos.lon).toFixed(6), Number(pos.lat).toFixed(6));
			},
		},
	}
</script>

<script module="LyMap" lang="renderjs">
	// 天地图接口
	const TDT_API = "https://api.tianditu.gov.***/api?v=4.0&tk=";
	export default {
		data() {
			return {
				// 初始化配置数据
				_config: {},
				// 地图实例
				_mapInstance: {},
				// 注记
				_markerList: [],
				// 地图事件
				_event: {},
			};
		},
		mounted() {
			// console.log('TDT_API', TDT_API);
		},
		methods: {
			// 初始化
			init(newValue, oldValue, ownerInstance, instance) {
				// 防止重复渲染
				if (!Object.keys(newValue).length) {
					return;
				}
				this._config = newValue;
				// 初始化地图
				if (typeof window.LyMap === 'function') {
					this._createMap();
				} else {
					const script = document.createElement('script');
					script.src = TDT_API + newValue.mapKey;
					script.onload = this._createMap.bind(this);
					document.head.appendChild(script);
				}
			},
			// 通过监听call来调用渲染层方法
			call(newValue, oldValue, ownerInstance, instance) {
				// console.log('renderjs的call方法newValue, oldValue, ownerInstance, instance', newValue, oldValue, ownerInstance, instance);
				if (this[newValue.name] && typeof this[newValue.name] === "function") {
					console.log('this[newValue.name]是个方法', this[newValue.name].name);
					this[newValue.name](newValue.data);
				}
			},
			// 创建地图
			_createMap() {
				// 创建地图实例
				try {
					this._mapInstance = new T.Map(this._config.mapId);
					this._mapInstance.addEventListener('load', () => this.$ownerInstance.callMethod('onMapLoad', this
						._config));
					setTimeout(() => this._mapInstance.centerAndZoom(new T.LngLat(this._config.lonlat[0], this._config
						.lonlat[1]), this._config.zoom), 100);
					this._mapInstance.setMapType(TMAP_HYBRID_MAP)
					this._bindEvent();
				} catch (err) {
					console.error(err);
				}
			},
			// 绑定事件
			_bindEvent() {
				try {
					// 绑定开始移动事件
					this._event = {};
					this._event.dragstart = (type, target) => {
						const center = this._mapInstance.getCenter();
						this.$ownerInstance.callMethod('onMapStartDrag', {
							lon: center.getLng(),
							lat: center.getLat()
						});
					};
					this._mapInstance.addEventListener('dragstart', this._event.dragstart.bind(this));
					// 绑定结束移动事件
					this._event.dragend = (type, target) => {
						const center = this._mapInstance.getCenter();
						this.$ownerInstance.callMethod('onMapEndDrag', {
							lon: center.getLng(),
							lat: center.getLat()
						});
					};
					this._mapInstance.addEventListener('dragend', this._event.dragend.bind(this));
					// 绑定地图缩放事件
					this._event.zoomend = (type, target) => {
						const center = this._mapInstance.getCenter();
						this.$ownerInstance.callMethod('onMapZoomEnd', {
							lon: center.getLng(),
							lat: center.getLat()
						});
					};
					this._mapInstance.addEventListener('zoomend', this._event.zoomend.bind(this));

					// 添加其它事件 详见:https://lbs.tianditu.gov.***/api/js4.0/class.html
				} catch (err) {
					console.error(err);
				}
			},
			// 卸载事件
			_unbindEvent() {
				const eventsKey = Object.keys(this._event);
				eventsKey.forEach(key => this._mapInstance.removeEventListener(key));
				this._event = null;
			},
			// 重置地图尺寸
			_resize() {
				try {
					// checkResize()通知地图其容器大小已更改。在更改了容器对象的大小后调用此方法,以便地图能够调整自己适合于新的大小。
					this._mapInstance.checkResize && this._mapInstance.checkResize();
				} catch (err) {
					console.error(err);
				}
			},
			// 设置选项
			_setOption(data) {
				if (data.type) {
					this._setType(data);
				}
				if (data.center) {
					this._setCenter({
						...data.center,
						zoom: data.zoom
					});
				}
				if (data.markers) {
					this._setMarkers(data);
				}
			},
			// 设置中心点
			_setCenter(data) {
				try {
					this._resize(); // 重置地图尺寸
					this._mapInstance.panTo(new T.LngLat(Number(data.lon), Number(data.lat)), data.zoom || this
						._mapInstance.getZoom());
				} catch (err) {
					console.error(err);
				}
			},
			// 设置地图显示类型
			_setType(data) {
				try {
					this._mapInstance.setMapType(data.type === 1 ? TMAP_SATELLITE_MAP : TMAP_NORMAL_MAP);
				} catch (err) {
					console.error(err);
				}
			},
			// 查看look
			_look() {
				try {
					const zzz = this._mapInstance.getCenter();
					// //创建标注对象
					// var marker = new T.Marker(zzz);
					// //向地图上添加标注
					// this._mapInstance.addOverLay(marker);
					console.log('aaaaaa', resulet);
				} catch (err) {
					console.error(err);
				}
			},
			// 设置地图缩放
			_setZoom(data) {
				try {
					this._mapInstance.setZoom(data.zoom);
				} catch (err) {
					console.error(err);
				}
			},
			// 设置注记
			_setMarkers(data) {
				try {
					// 清空当前所有注记
					if (!this._markerList) this._markerList = [];
					this._markerList.forEach(marker => this._mapInstance.removeOverLay(marker));
					this._markerList = [];
					// 创建新注记
					data.markers && data.markers.forEach(item => {
						const icon = new T.Icon({
							iconUrl: item.icon,
							iconSize: new T.Point(item.width || 24, item.height || 24),
							iconAnchor: new T.Point(item.offsetX || item.width / 2, item.offsetY || item
								.height)
						});
						const marker = new T.Marker(new T.LngLat(item.lon, item.lat), {
							icon: icon
						});
						this._markerList.push(marker);
						this._mapInstance.addOverLay(marker);
					});
				} catch (err) {
					console.error(err);
				}
			},
			// 释放地图
			_dispose() {
				delete this._mapInstance;
				this._mapInstance = null;
				this._unbindEvent();
			}
		},
	};
</script>

<style lang="scss" scoped>
	.ly-map-wrapper {
		width: 100%;
		height: 100%;
		position: relative;
		overflow: hidden;
		background: #f0f0f0;

		.ly-map {
			width: 100%;
			height: 50%;
		}

		// 中心点图标样式 
		.ly-center-icon {
			position: absolute;
			z-index: 401;
			left: 50%;
			top: 25%;
			transform: translateX(-50%) translateY(-100%);
			width: 62rpx;
			height: 100rpx;
		}

		// 右下角定位图标样式
		.ly-location-icon {
			position: absolute;
			z-index: 401;
			right: 24rpx;
			top: 40%;
			// bottom: 24rpx;
			width: 72rpx;
			height: 72rpx;
			background: #ffffff;
			border-radius: 12rpx;
			display: flex;
			align-items: center;
			justify-content: center;
			box-shadow: 0 0 8rpx rgba(0, 0, 0, .15);

			.icon {
				width: 44rpx;
				height: 44rpx;
			}
		}
	}
</style>

四、用到的方法 地理空间搜索范围计算函数

        SearchRangePoint.js

// 搜索传入中心点坐标周围的点 
/**
 * 地球半径(公里)
 */
const EARTH_RADIUS = 6371;

/**
 * 将角度转换为弧度
 * @param {number} degree - 角度值
 * @returns {number} 弧度值
 */
function toRadians(degree) {
	return degree * Math.PI / 180;
}

/**
 * 将弧度转换为角度
 * @param {number} radian - 弧度值
 * @returns {number} 角度值
 */
function toDegrees(radian) {
	return radian * 180 / Math.PI;
}

/**
 * 计算给定中心点和距离的边界经纬度
 * @param {number} centerLat - 中心纬度(度)
 * @param {number} centerLon - 中心经度(度)
 * @param {number} distance - 距离(公里)
 * @returns {Object} 包含 minLat, maxLat, minLon, maxLon 的对象
 */
function calculateBounds(centerLat, centerLon, distance) {
	const dLat = (distance / EARTH_RADIUS) * (180 / Math.PI);
	const dLon = (distance / (EARTH_RADIUS * Math.cos(toRadians(centerLat)))) * (180 / Math.PI);

	const minLat = centerLat - dLat;
	const maxLat = centerLat + dLat;
	const minLon = centerLon - dLon;
	const maxLon = centerLon + dLon;

	return {
		minLat: parseFloat(minLat.toFixed(6)),
		maxLat: parseFloat(maxLat.toFixed(6)),
		minLon: parseFloat(minLon.toFixed(6)),
		maxLon: parseFloat(maxLon.toFixed(6))
	};
}

/**
 * 封装的地理空间搜索范围计算函数
 * @param {Object} options - 参数对象
 * @param {number} options.latitude - 中心纬度
 * @param {number} options.longitude - 中心经度
 * @param {number} [options.distance=10] - 搜索距离(公里),默认为 10 公里
 * @returns {Object} 包含 minLat, maxLat, minLon, maxLon 的对象
 */
export function getSearchBounds({ latitude, longitude, distance = 100 }) {
	if (typeof latitude !== 'number' || typeof longitude !== 'number') {
		throw new Error('latitude 和 longitude 必须是数字');
	}
	if (typeof distance !== 'number' || distance < 0) {
		throw new Error('distance 必须是一个非负数');
	}

	return calculateBounds(latitude, longitude, distance);
}

其他图标可以用你们本地图标 ,我这边便不再展示。

end。感谢观看

转载请说明出处内容投诉
CSS教程网 » uniapp使用renderjs引入天地图实现地图选点以及搜索附近poi点

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买