前言
項(xiàng)目中有一個(gè)需求,就是需要繪制一個(gè)圓,并且繪制的時(shí)候還要設(shè)置方位角,最后返回圓的坐標(biāo)集合和方位角。本功能使用Leaflet-Geoman+Turf.js+leaflet實(shí)現(xiàn)。
方位角簡(jiǎn)介
在陸地導(dǎo)航中,方位角通常表示為 alpha、α,并定義為從北基線或子午線順時(shí)針測(cè)量的水平角。方位角也被更廣泛地定義為從任何固定參考平面或容易建立的基準(zhǔn)方向線順時(shí)針測(cè)量的水平角度。
今天,方位角的參考平面通常是真北,測(cè)量為 0° 方位角,但也可以使用其他角度單位(grad、mil)。 在 360 度圓上順時(shí)針移動(dòng),東方位角為 90°,南方位角為 180°,西方位角為 270°。也有例外:一些導(dǎo)航系統(tǒng)使用南方作為參考矢量。任何方向都可以作為參考向量,只要明確定義即可。
很常見(jiàn)的是,方位角或羅盤(pán)方位在一個(gè)系統(tǒng)中表示,其中北或南可以是零,并且可以從零順時(shí)針或逆時(shí)針測(cè)量角度。
首先說(shuō)明的參考方向始終是北或南,最后說(shuō)明的轉(zhuǎn)向方向是東或西。選擇方向,使它們之間的角度為正,介于 0 和 90 度之間。如果方位恰好在基點(diǎn)之一的方向上,則使用不同的符號(hào)。
**注意:**項(xiàng)目中我們規(guī)定正北為0° 方位角,順時(shí)針逐漸增加,直到360° 方位角
Leaflet-Geoman簡(jiǎn)介
我的理解就是一個(gè)leaflet的繪制插件,具體可以查看Leaflet-Geoman官網(wǎng),本功能就是使用它繪制Circle
Turf.js簡(jiǎn)介
Turf.js 是一個(gè)用于地理空間計(jì)算的 JavaScript 庫(kù)。它提供了許多地理空間操作的函數(shù),如點(diǎn)線面的創(chuàng)建、緩沖區(qū)計(jì)算、距離計(jì)算、區(qū)域合并等,方便在前端應(yīng)用中處理地理空間數(shù)據(jù)和實(shí)現(xiàn)地圖相關(guān)功能。Turf.js 不依賴于任何地圖庫(kù),可以在任何 JavaScript 環(huán)境中使用。
繪制Circle可以使用Leaflet-Geoman繪制,但是方位角的話不能直接獲取,所以我想用turf.js里面的**bearing**,取兩點(diǎn),找出它們之間的地理方位,即從北線(0度)開(kāi)始測(cè)量的角度。這兩點(diǎn)就是繪制的圓的圓心(start),鼠標(biāo)移動(dòng)的坐標(biāo)點(diǎn)(end),這樣就能實(shí)時(shí)得到方位角了。
UseWindCircle.js完整代碼
/**
* @ClassName UseWindCircle.js
* @Description 風(fēng)圈繪制操作hook
* @Author ZhangJun
* @Date 2024/1/9 15:38
**/
import 'leaflet.pm'
import 'leaflet.pm/dist/leaflet.pm.css'
import * as turf from '@turf/turf'
import { ref, onUnmounted, reactive } from 'vue'
import BigNumber from 'bignumber.js'
export function useWindCircle(mainMap, geometryType = 'Circle', drawComplete = null, drawLayer = undefined) {
//繪制完成后的要素幾何圖層
let targetFeatureLayer = null
//繪制事件狀態(tài)
let status = ref('start')
//生成圓的坐標(biāo)的精度
let steps = ref(10)
//生成圓的單位距離
let units = ref('kilometers')//meters
//方向角
let direction = ref(null)
//繪制的圓的坐標(biāo)集合
let coords = ref([])
//用于標(biāo)記方向的popup
let directionPopup = new L.popup({ closeButton: false })
//圓心坐標(biāo)
let centerPosition = null
if (mainMap) {
//關(guān)閉的時(shí)候一定要銷毀
onUnmounted(() => {
closeDraw()
mainMap?.removeLayer(drawLayer)
})
if (!drawLayer) {
drawLayer = L.featureGroup([])
drawLayer.addTo(mainMap)
}
// 添加繪制工具
mainMap.pm.setLang('zh')
mainMap.pm.addControls({
position: 'topleft',
drawPolygon: false, //繪制多邊形
drawMarker: false, //繪制標(biāo)記點(diǎn)
drawCircleMarker: false, //繪制圓形標(biāo)記
drawPolyline: false, //繪制線條
drawRectangle: false, //繪制矩形
drawCircle: false, //繪制圓圈
editMode: false, //編輯多邊形
dragMode: false, //拖動(dòng)多邊形
cutPolygon: false, //添加?個(gè)按鈕以刪除多邊形??的部分內(nèi)容
removalMode: false, //清除多邊形
})
// 全局設(shè)置繪制樣式
mainMap.pm.setPathOptions({
color: 'orange',
fillColor: 'green',
fillOpacity: 0.4,
})
//初始化事件
let initEvents = () => {
//繪制開(kāi)始(可以多次繪制)
mainMap.on('pm:drawstart', ({ workingLayer }) => {
//中心點(diǎn)改變就進(jìn)這里
workingLayer.on('pm:centerplaced', (e) => {
status.value = 'start'
centerPosition = e.latlng
//打開(kāi)方向的popup
directionPopup?.setLatLng(centerPosition).openOn(mainMap)
})
})
mainMap.on('mousemove', (e) => {
if (centerPosition) {
let latLng = e.latlng
let startPoint = turf.point([centerPosition.lng, centerPosition.lat])
let endPoint = turf.point([latLng.lng, latLng.lat])
//獲取圓心和現(xiàn)在鼠標(biāo)坐標(biāo)的中心點(diǎn)數(shù)據(jù)
let popupPosition = turf.midpoint(startPoint, endPoint)
let [lng, lat] = popupPosition.geometry.coordinates
//計(jì)算現(xiàn)在的方向位置,并賦值方向
let direction_temp = getDirection(centerPosition, latLng)
direction.value = new BigNumber(direction_temp).toFixed(2)
setPopupContent({ lat, lng }, `<b>風(fēng)向:</b>${direction.value}°`)
}
})
//繪制完成
mainMap.on('pm:create', (e) => {
//清除上一個(gè)繪制的緩沖區(qū)
clearDrawLayer()
status.value = 'end'
let { layer } = e
targetFeatureLayer = layer
layer.remove()
addLayersToDrawLayer([targetFeatureLayer])
mainMap.pm.enableDraw(geometryType)
mainMap.closePopup(directionPopup)
//繪制完成的回調(diào)
if (typeof drawComplete === 'function') {
let result = getResult(targetFeatureLayer)
drawComplete(result)
}
})
mainMap.on('pm:globalremovalmodetoggled', (e) => {
console.log(e, '清除圖層時(shí)調(diào)用')
})
}
//移除事件
let removeEvents = () => {
//取消時(shí)間的監(jiān)聽(tīng)
mainMap?.off('pm:drawstart')
mainMap?.off('pm:create')
mainMap?.off('mousemove')
}
//清除原來(lái)繪制的內(nèi)容
let clearDrawLayer = () => {
drawLayer?.clearLayers()
targetFeatureLayer = null
}
//添加要素到drawLayer
let addLayersToDrawLayer = (features = []) => {
features?.forEach(feature => {
drawLayer.addLayer(feature)
})
}
//關(guān)閉繪制功能
let closeDraw = () => {
mainMap.pm.disableDraw(geometryType)
//清空繪制的幾何
clearDrawLayer()
//一定要移除事件,否則事件之間會(huì)有干擾
removeEvents()
}
//開(kāi)始繪制
let startDraw = (type = geometryType) => {
//初始化事件
initEvents()
if (type !== geometryType) {
geometryType = type
}
if (type) {
//默認(rèn)繪制幾何
mainMap.pm.enableDraw(type)
}
}
//設(shè)置需要顯示的方位popup內(nèi)容
let setPopupContent = (latLng, content = '') => {
directionPopup.setLatLng(latLng).setContent(content)
}
//獲取緩沖區(qū)的坐標(biāo)集合
let getResult = (target = targetFeatureLayer) => {
if (target) {
let { lat, lng } = target.getLatLng()
let center = [lng, lat]
let radius = target.getRadius()
let options = { steps: steps.value, units: units.value, properties: { foo: 'bar' } }
let circle = turf.circle(center, radius, options)
if (circle?.geometry) {
//獲取輸入 feature 并將它們的所有坐標(biāo)從 [x, y] 翻轉(zhuǎn)為 [y, x]。
let temp = turf.flip(circle)
coords.value = turf.getCoords(temp)
return { direction: direction.value, coords: coords.value }
}
}
return { direction: direction.value, coords: coords.value }
}
//取兩點(diǎn),找出它們之間的地理方位,即從北線(0度)開(kāi)始測(cè)量的角度。
let getDirection = (start = centerPosition, end) => {
start = [start.lng, start.lat]
end = [end.lng, end.lat]
return turf.bearing(start, end, { final: true })
}
return { status, closeDraw, drawLayer, startDraw, steps, units, coords, direction }
}
return {}
}
UseWindCircle.js使用
//風(fēng)圈使用的hook
let {
startDraw: startWindCircle,
closeDraw: closeWindCircle,
units,
steps,
} = useWindCircle(props.lMap, undefined, e => {
alert(JSON.stringify(e))
})
使用startWindCircle()開(kāi)始繪制,closeWindCircle()結(jié)束繪制,繪制完成會(huì)進(jìn)入上面的回調(diào)函數(shù),并返回我們要的圓的輪廓坐標(biāo)還有方向角({direction:xxx,coords:[]})
效果如下
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-821567.html
本文為學(xué)習(xí)筆記,僅供參考文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-821567.html
到了這里,關(guān)于leaflet學(xué)習(xí)筆記-帶有方位角信息的圓的繪制(七)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!