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。感谢观看