【类 型】:
【原 因】: 【过 程】: 【影 响】:
This commit is contained in:
parent
5f9208f6a0
commit
9663da692c
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import mapboxgl from 'mapbox-gl'
|
import mapboxgl from 'mapbox-gl'
|
||||||
import { MapboxStyleSwitcherControl, FollowControl, CustomFullscreenControl, NoFlyControl, SaveToFileControl } from '@/utils/mapboxgl_plugs'
|
import { MapboxStyleSwitcherControl, FollowControl, CustomFullscreenControl, NoFlyControl, SaveToFileControl, PolygonToggleControl } from '@/utils/mapboxgl_plugs'
|
||||||
import planeIcon from '@/assets/svg/plane.svg'
|
import planeIcon from '@/assets/svg/plane.svg'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -171,6 +171,10 @@ export default {
|
|||||||
enableNofly: { // 禁飞区 设置 组件
|
enableNofly: { // 禁飞区 设置 组件
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
showNofly: { // 显示 禁飞区 组件
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -341,21 +345,41 @@ export default {
|
|||||||
|
|
||||||
// 禁飞区 限飞区 设置组件
|
// 禁飞区 限飞区 设置组件
|
||||||
if (this.enableNofly) {
|
if (this.enableNofly) {
|
||||||
const defaultPolygons = this.$store.state.noflyData[0]
|
const noflyPolygons = this.$store.state.noflyData[0]
|
||||||
|
const restrictflyPolygons = this.$store.state.noflyData[1]
|
||||||
const shopId = this.$store.state.user.shop_id
|
const shopId = this.$store.state.user.shop_id
|
||||||
|
|
||||||
this.map.addControl(new NoFlyControl({
|
this.map.addControl(new NoFlyControl({
|
||||||
defaultPolygons,
|
noflyPolygons,
|
||||||
shopId, // 传给 NoFlyControl
|
restrictflyPolygons,
|
||||||
onSave: (polygons) => {
|
shopId,
|
||||||
if (typeof this.onSave === 'function') {
|
onSave: (nofly, limit) => {
|
||||||
this.onSave(polygons)
|
console.log('保存成功:', nofly, limit)
|
||||||
} else {
|
},
|
||||||
console.log('禁飞区保存数据:', polygons)
|
onDrawFinish: (nofly) => {
|
||||||
}
|
console.log('禁飞区绘制完成:', nofly)
|
||||||
|
},
|
||||||
|
onLimitFinish: (limit) => {
|
||||||
|
console.log('限飞区绘制完成:', limit)
|
||||||
}
|
}
|
||||||
}), 'top-left')
|
}), 'top-left')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 显示禁飞区 限飞区控件
|
||||||
|
if (this.showNofly) {
|
||||||
|
const noflyPolygons = this.$store.state.noflyData[0] || []
|
||||||
|
const restrictflyPolygons = this.$store.state.noflyData[1] || []
|
||||||
|
|
||||||
|
this.map.addControl(new PolygonToggleControl({
|
||||||
|
defaultIconClass: 'iconfont icon-polygon-default f-s-20',
|
||||||
|
activeIconClass: 'iconfont icon-polygon-active f-s-20 brandFontColor',
|
||||||
|
noflyPolygons,
|
||||||
|
restrictflyPolygons,
|
||||||
|
onDraw: (active) => {
|
||||||
|
console.log('禁飞/限飞区域控件状态:', active)
|
||||||
|
}
|
||||||
|
}), 'top-right')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @description 通用地图图层和数据源清除方法
|
* @description 通用地图图层和数据源清除方法
|
||||||
@ -692,6 +716,107 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* @description: 绘制一个多边形区域,并在中心显示文字
|
||||||
|
* @param {Array} coordinatesArray 多边形坐标数组(格式为 [ [lng, lat], ... ],首尾闭合)
|
||||||
|
* @param {String} polygonId 图层 ID
|
||||||
|
* @param {String} fillColor 填充颜色(默认红色)
|
||||||
|
* @param {String} labelText 中心显示的文字(为空则不显示)
|
||||||
|
*/
|
||||||
|
drawPolygonWithLabel (coordinatesArray, polygonId = 'polygon-area', fillColor = '#F33', labelText = '') {
|
||||||
|
// GeoJSON 数据
|
||||||
|
const polygonGeoJSON = {
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [coordinatesArray]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 内部函数:计算中心点
|
||||||
|
const calculateCenter = (coords) => {
|
||||||
|
let lngSum = 0
|
||||||
|
let latSum = 0
|
||||||
|
coords.forEach(([lng, lat]) => {
|
||||||
|
lngSum += lng
|
||||||
|
latSum += lat
|
||||||
|
})
|
||||||
|
return [lngSum / coords.length, latSum / coords.length]
|
||||||
|
}
|
||||||
|
|
||||||
|
const center = calculateCenter(coordinatesArray)
|
||||||
|
|
||||||
|
const labelGeoJSON = {
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: center
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
title: labelText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加或更新多边形图层
|
||||||
|
if (this.map.getLayer(polygonId)) {
|
||||||
|
this.map.getSource(polygonId).setData(polygonGeoJSON)
|
||||||
|
} else {
|
||||||
|
this.map.addSource(polygonId, {
|
||||||
|
type: 'geojson',
|
||||||
|
data: polygonGeoJSON
|
||||||
|
})
|
||||||
|
|
||||||
|
this.map.addLayer({
|
||||||
|
id: polygonId,
|
||||||
|
type: 'fill',
|
||||||
|
source: polygonId,
|
||||||
|
paint: {
|
||||||
|
'fill-color': fillColor,
|
||||||
|
'fill-opacity': 0.4
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.map.addLayer({
|
||||||
|
id: `${polygonId}-outline`,
|
||||||
|
type: 'line',
|
||||||
|
source: polygonId,
|
||||||
|
paint: {
|
||||||
|
'line-color': fillColor,
|
||||||
|
'line-width': 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加或更新文字标签
|
||||||
|
if (labelText) {
|
||||||
|
const labelSourceId = `${polygonId}-label`
|
||||||
|
const labelLayerId = `${polygonId}-label-layer`
|
||||||
|
|
||||||
|
if (this.map.getLayer(labelLayerId)) {
|
||||||
|
this.map.getSource(labelSourceId).setData(labelGeoJSON)
|
||||||
|
} else {
|
||||||
|
this.map.addSource(labelSourceId, {
|
||||||
|
type: 'geojson',
|
||||||
|
data: labelGeoJSON
|
||||||
|
})
|
||||||
|
|
||||||
|
this.map.addLayer({
|
||||||
|
id: labelLayerId,
|
||||||
|
type: 'symbol',
|
||||||
|
source: labelSourceId,
|
||||||
|
layout: {
|
||||||
|
'text-field': ['get', 'title'],
|
||||||
|
'text-size': 14,
|
||||||
|
'text-offset': [0, 0.5],
|
||||||
|
'text-anchor': 'top'
|
||||||
|
},
|
||||||
|
paint: {
|
||||||
|
'text-color': '#000000'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* @description: 创建一个飞机
|
* @description: 创建一个飞机
|
||||||
* @param {*} plane 飞机对象
|
* @param {*} plane 飞机对象
|
||||||
|
@ -218,44 +218,65 @@ export class CustomFullscreenControl extends mapboxgl.FullscreenControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 禁飞区 限飞区 保存 删除控件
|
// 设置禁飞区 限飞区 保存 删除控件
|
||||||
|
|
||||||
export class NoFlyControl {
|
export class NoFlyControl {
|
||||||
constructor (options = {}) {
|
constructor (options = {}) {
|
||||||
this._map = null
|
this._map = null
|
||||||
this._container = null
|
this._container = null
|
||||||
|
|
||||||
this._draw = null
|
this._draw = null
|
||||||
this._onDrawFinish = options.onDrawFinish || function () {}
|
this._onDrawFinish = options.onDrawFinish || function () {}
|
||||||
this._defaultPolygons = options.defaultPolygons || []
|
this._noflyPolygons = options.noflyPolygons || []
|
||||||
|
|
||||||
|
this._onLimitFinish = options.onLimitFinish || function () {}
|
||||||
|
this._restrictflyPolygons = options.restrictflyPolygons || []
|
||||||
|
|
||||||
this._onSave = options.onSave || function () {}
|
this._onSave = options.onSave || function () {}
|
||||||
this._shopId = options.shopId
|
this._shopId = options.shopId
|
||||||
|
|
||||||
|
this._activeMode = 'nofly' // 当前绘制类型
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd (map) {
|
onAdd (map) {
|
||||||
this._map = map
|
this._map = map
|
||||||
|
|
||||||
// 创建按钮容器
|
|
||||||
this._container = document.createElement('div')
|
this._container = document.createElement('div')
|
||||||
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'
|
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'
|
||||||
|
|
||||||
// 绘制按钮
|
// --- 绘制禁飞区按钮 ---
|
||||||
const drawButton = document.createElement('button')
|
const drawButton = document.createElement('button')
|
||||||
drawButton.className = 'mapboxgl-ctrl-icon'
|
drawButton.className = 'mapboxgl-ctrl-icon'
|
||||||
drawButton.type = 'button'
|
drawButton.type = 'button'
|
||||||
drawButton.innerHTML = '✏️'
|
drawButton.innerHTML = '✏️'
|
||||||
drawButton.title = '绘制禁飞区'
|
drawButton.title = '绘制禁飞区'
|
||||||
drawButton.onclick = () => this._enableDraw()
|
drawButton.onclick = () => {
|
||||||
|
this._activeMode = 'nofly'
|
||||||
|
this._enableDraw()
|
||||||
|
}
|
||||||
this._container.appendChild(drawButton)
|
this._container.appendChild(drawButton)
|
||||||
|
|
||||||
// 保存按钮(磁盘图标)
|
// --- 绘制限飞区按钮 ---
|
||||||
|
const limitButton = document.createElement('button')
|
||||||
|
limitButton.className = 'mapboxgl-ctrl-icon'
|
||||||
|
limitButton.type = 'button'
|
||||||
|
limitButton.innerHTML = '✒️'
|
||||||
|
limitButton.title = '绘制限飞区'
|
||||||
|
limitButton.onclick = () => {
|
||||||
|
this._activeMode = 'limit'
|
||||||
|
this._enableDraw()
|
||||||
|
}
|
||||||
|
this._container.appendChild(limitButton)
|
||||||
|
|
||||||
|
// --- 保存按钮 ---
|
||||||
const saveButton = document.createElement('button')
|
const saveButton = document.createElement('button')
|
||||||
saveButton.className = 'mapboxgl-ctrl-icon'
|
saveButton.className = 'mapboxgl-ctrl-icon'
|
||||||
saveButton.type = 'button'
|
saveButton.type = 'button'
|
||||||
saveButton.innerHTML = '💾'
|
saveButton.innerHTML = '💾'
|
||||||
saveButton.title = '保存禁飞区'
|
saveButton.title = '保存禁飞区及限飞区'
|
||||||
saveButton.onclick = () => this._savePolygons()
|
saveButton.onclick = () => this._savePolygons()
|
||||||
this._container.appendChild(saveButton)
|
this._container.appendChild(saveButton)
|
||||||
|
|
||||||
// 删除按钮(仅删除选中的图形)
|
// --- 删除按钮 ---
|
||||||
const deleteButton = document.createElement('button')
|
const deleteButton = document.createElement('button')
|
||||||
deleteButton.className = 'mapboxgl-ctrl-icon'
|
deleteButton.className = 'mapboxgl-ctrl-icon'
|
||||||
deleteButton.type = 'button'
|
deleteButton.type = 'button'
|
||||||
@ -267,62 +288,38 @@ export class NoFlyControl {
|
|||||||
// 初始化 Draw 控件
|
// 初始化 Draw 控件
|
||||||
this._draw = new MapboxDraw({
|
this._draw = new MapboxDraw({
|
||||||
displayControlsDefault: false,
|
displayControlsDefault: false,
|
||||||
styles: [
|
styles: this._getDrawStyles()
|
||||||
{
|
|
||||||
id: 'gl-draw-polygon-fill',
|
|
||||||
type: 'fill',
|
|
||||||
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
|
|
||||||
paint: {
|
|
||||||
'fill-color': '#ff0000',
|
|
||||||
'fill-opacity': 0.3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'gl-draw-polygon-stroke-active',
|
|
||||||
type: 'line',
|
|
||||||
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
|
|
||||||
paint: {
|
|
||||||
'line-color': '#ff0000',
|
|
||||||
'line-width': 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'gl-draw-polygon-and-line-vertex-halo-active',
|
|
||||||
type: 'circle',
|
|
||||||
filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
|
|
||||||
paint: {
|
|
||||||
'circle-radius': 7,
|
|
||||||
'circle-color': '#FFF'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'gl-draw-polygon-and-line-vertex-active',
|
|
||||||
type: 'circle',
|
|
||||||
filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
|
|
||||||
paint: {
|
|
||||||
'circle-radius': 5,
|
|
||||||
'circle-color': '#f00'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
map.addControl(this._draw)
|
map.addControl(this._draw)
|
||||||
|
|
||||||
// 加载默认禁飞区
|
// 加载已有禁飞区
|
||||||
if (this._defaultPolygons.length > 0) {
|
if (this._noflyPolygons.length > 0) {
|
||||||
const features = this._defaultPolygons.map(coords => ({
|
const features = this._noflyPolygons.map(coords => ({
|
||||||
type: 'Feature',
|
type: 'Feature',
|
||||||
geometry: {
|
geometry: {
|
||||||
type: 'Polygon',
|
type: 'Polygon',
|
||||||
coordinates: [coords]
|
coordinates: [coords]
|
||||||
},
|
},
|
||||||
properties: {}
|
properties: {
|
||||||
|
type: 'nofly'
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
this._draw.set({
|
this._draw.add({ type: 'FeatureCollection', features })
|
||||||
type: 'FeatureCollection',
|
}
|
||||||
features
|
|
||||||
})
|
// 加载已有限飞区
|
||||||
|
if (this._restrictflyPolygons.length > 0) {
|
||||||
|
const features = this._restrictflyPolygons.map(coords => ({
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [coords]
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
type: 'limit'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
this._draw.add({ type: 'FeatureCollection', features })
|
||||||
}
|
}
|
||||||
|
|
||||||
map.on('draw.create', this._handleDraw.bind(this))
|
map.on('draw.create', this._handleDraw.bind(this))
|
||||||
@ -347,10 +344,29 @@ export class NoFlyControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleDraw (e) {
|
_handleDraw (e) {
|
||||||
const features = this._draw.getAll()
|
const features = e.features
|
||||||
if (features.features.length > 0) {
|
if (features.length === 0) return
|
||||||
const coordinates = features.features.map(f => f.geometry.coordinates)
|
|
||||||
this._onDrawFinish(coordinates)
|
const type = this._activeMode === 'limit' ? 'limit' : 'nofly'
|
||||||
|
|
||||||
|
features.forEach(f => {
|
||||||
|
f.properties.type = type
|
||||||
|
})
|
||||||
|
|
||||||
|
this._draw.delete(features.map(f => f.id))
|
||||||
|
this._draw.add({
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features
|
||||||
|
})
|
||||||
|
|
||||||
|
const allCoords = this._draw.getAll().features
|
||||||
|
.filter(f => f.properties.type === type)
|
||||||
|
.map(f => f.geometry.coordinates)
|
||||||
|
|
||||||
|
if (type === 'nofly') {
|
||||||
|
this._onDrawFinish(allCoords)
|
||||||
|
} else {
|
||||||
|
this._onLimitFinish(allCoords)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,22 +380,242 @@ export class NoFlyControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _savePolygons () {
|
async _savePolygons () {
|
||||||
if (!this._draw) return
|
|
||||||
const allFeatures = this._draw.getAll()
|
const allFeatures = this._draw.getAll()
|
||||||
|
|
||||||
const polygons = allFeatures.features
|
const nofly = allFeatures.features
|
||||||
.filter(f => f.geometry.type === 'Polygon')
|
.filter(f => f.properties.type === 'nofly')
|
||||||
.map(f => f.geometry.coordinates[0]) // 解开一层数组 ✅
|
.map(f => f.geometry.coordinates[0])
|
||||||
|
|
||||||
|
const limit = allFeatures.features
|
||||||
|
.filter(f => f.properties.type === 'limit')
|
||||||
|
.map(f => f.geometry.coordinates[0])
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const shopId = this._shopId
|
const shopId = this._shopId
|
||||||
await setNoflyData(shopId, polygons, [])
|
await setNoflyData(shopId, nofly, limit)
|
||||||
|
this._onSave(nofly, limit)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Message.error('上传禁飞区数据时发生错误')
|
Message.error('上传数据失败')
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._onSave(polygons)
|
_getDrawStyles () {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 'gl-draw-polygon-fill',
|
||||||
|
type: 'fill',
|
||||||
|
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
|
||||||
|
paint: {
|
||||||
|
'fill-color': ['case',
|
||||||
|
['==', ['get', 'type'], 'nofly'], '#F33',
|
||||||
|
['==', ['get', 'type'], 'limit'], '#F83',
|
||||||
|
'#F83'
|
||||||
|
],
|
||||||
|
'fill-opacity': 0.3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gl-draw-polygon-stroke-active',
|
||||||
|
type: 'line',
|
||||||
|
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
|
||||||
|
paint: {
|
||||||
|
'line-color': ['case',
|
||||||
|
['==', ['get', 'type'], 'nofly'], '#F33',
|
||||||
|
['==', ['get', 'type'], 'limit'], '#F83',
|
||||||
|
'#F83'
|
||||||
|
],
|
||||||
|
'line-width': 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gl-draw-polygon-and-line-vertex-halo-active',
|
||||||
|
type: 'circle',
|
||||||
|
filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
|
||||||
|
paint: {
|
||||||
|
'circle-radius': 7,
|
||||||
|
'circle-color': '#FFF'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gl-draw-polygon-and-line-vertex-active',
|
||||||
|
type: 'circle',
|
||||||
|
filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
|
||||||
|
paint: {
|
||||||
|
'circle-radius': 5,
|
||||||
|
'circle-color': '#F83'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示禁飞区 限飞区
|
||||||
|
export class PolygonToggleControl {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {{
|
||||||
|
* defaultIconClass: string,
|
||||||
|
* activeIconClass: string,
|
||||||
|
* onDraw?: Function, // 激活时回调,传入激活状态
|
||||||
|
* noflyPolygons: Array, // 禁飞区多边形数据,数组里是多边形坐标数组
|
||||||
|
* restrictflyPolygons: Array // 限飞区多边形数据
|
||||||
|
* }} options
|
||||||
|
*/
|
||||||
|
constructor ({ defaultIconClass, activeIconClass, onDraw, noflyPolygons, restrictflyPolygons }) {
|
||||||
|
this._defaultIconClass = defaultIconClass
|
||||||
|
this._activeIconClass = activeIconClass
|
||||||
|
this._onDraw = onDraw
|
||||||
|
this._noflyPolygons = noflyPolygons
|
||||||
|
this._restrictflyPolygons = restrictflyPolygons
|
||||||
|
this._isActive = false
|
||||||
|
this._map = null
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd (map) {
|
||||||
|
this._map = map
|
||||||
|
this._container = document.createElement('div')
|
||||||
|
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'
|
||||||
|
|
||||||
|
this._button = document.createElement('button')
|
||||||
|
this._button.className = this._defaultIconClass
|
||||||
|
this._button.onclick = this._handleClick.bind(this)
|
||||||
|
|
||||||
|
this._container.appendChild(this._button)
|
||||||
|
return this._container
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleClick () {
|
||||||
|
this._isActive = !this._isActive
|
||||||
|
this._button.className = this._isActive ? this._activeIconClass : this._defaultIconClass
|
||||||
|
|
||||||
|
if (this._isActive) {
|
||||||
|
// 激活时绘制所有禁飞区和限飞区多边形
|
||||||
|
this._drawPolygons()
|
||||||
|
} else {
|
||||||
|
// 取消激活时移除所有相关图层
|
||||||
|
this._removePolygons()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._onDraw) this._onDraw(this._isActive)
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawPolygons () {
|
||||||
|
// 禁飞区用颜色 #FF3333,id 用 nofly-0、nofly-1 ...
|
||||||
|
this._noflyPolygons.forEach((coords, idx) => {
|
||||||
|
this._drawPolygonWithLabel(coords, `nofly-${idx}`, '#FF3333', '禁飞区')
|
||||||
|
})
|
||||||
|
|
||||||
|
// 限飞区用颜色 #FF8833,id 用 restrictfly-0、restrictfly-1 ...
|
||||||
|
this._restrictflyPolygons.forEach((coords, idx) => {
|
||||||
|
this._drawPolygonWithLabel(coords, `restrictfly-${idx}`, '#FF8833', '限飞区')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_removePolygons () {
|
||||||
|
// 卸载禁飞区相关图层和source
|
||||||
|
this._noflyPolygons.forEach((_, idx) => {
|
||||||
|
this._removePolygonLayers(`nofly-${idx}`)
|
||||||
|
})
|
||||||
|
// 卸载限飞区相关图层和source
|
||||||
|
this._restrictflyPolygons.forEach((_, idx) => {
|
||||||
|
this._removePolygonLayers(`restrictfly-${idx}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_removePolygonLayers (baseId) {
|
||||||
|
const outlineId = `${baseId}-outline`
|
||||||
|
const labelLayerId = `${baseId}-label-layer`
|
||||||
|
const labelSourceId = `${baseId}-label`
|
||||||
|
|
||||||
|
if (this._map.getLayer(labelLayerId)) this._map.removeLayer(labelLayerId)
|
||||||
|
if (this._map.getSource(labelSourceId)) this._map.removeSource(labelSourceId)
|
||||||
|
|
||||||
|
if (this._map.getLayer(outlineId)) this._map.removeLayer(outlineId)
|
||||||
|
if (this._map.getLayer(baseId)) this._map.removeLayer(baseId)
|
||||||
|
if (this._map.getSource(baseId)) this._map.removeSource(baseId)
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawPolygonWithLabel (coordinatesArray, polygonId, fillColor, labelText) {
|
||||||
|
// 计算中心点
|
||||||
|
const calculateCenter = (coords) => {
|
||||||
|
let lngSum = 0; let latSum = 0
|
||||||
|
coords.forEach(([lng, lat]) => { lngSum += lng; latSum += lat })
|
||||||
|
return [lngSum / coords.length, latSum / coords.length]
|
||||||
|
}
|
||||||
|
|
||||||
|
const polygonGeoJSON = {
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [coordinatesArray]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const center = calculateCenter(coordinatesArray)
|
||||||
|
|
||||||
|
const labelGeoJSON = {
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: center
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
title: labelText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._map.getLayer(polygonId)) {
|
||||||
|
this._map.getSource(polygonId).setData(polygonGeoJSON)
|
||||||
|
} else {
|
||||||
|
this._map.addSource(polygonId, { type: 'geojson', data: polygonGeoJSON })
|
||||||
|
|
||||||
|
this._map.addLayer({
|
||||||
|
id: polygonId,
|
||||||
|
type: 'fill',
|
||||||
|
source: polygonId,
|
||||||
|
paint: { 'fill-color': fillColor, 'fill-opacity': 0.4 }
|
||||||
|
})
|
||||||
|
|
||||||
|
this._map.addLayer({
|
||||||
|
id: `${polygonId}-outline`,
|
||||||
|
type: 'line',
|
||||||
|
source: polygonId,
|
||||||
|
paint: { 'line-color': fillColor, 'line-width': 2 }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labelText) {
|
||||||
|
const labelSourceId = `${polygonId}-label`
|
||||||
|
const labelLayerId = `${polygonId}-label-layer`
|
||||||
|
|
||||||
|
if (this._map.getLayer(labelLayerId)) {
|
||||||
|
this._map.getSource(labelSourceId).setData(labelGeoJSON)
|
||||||
|
} else {
|
||||||
|
this._map.addSource(labelSourceId, { type: 'geojson', data: labelGeoJSON })
|
||||||
|
|
||||||
|
this._map.addLayer({
|
||||||
|
id: labelLayerId,
|
||||||
|
type: 'symbol',
|
||||||
|
source: labelSourceId,
|
||||||
|
layout: {
|
||||||
|
'text-field': ['get', 'title'],
|
||||||
|
'text-size': 14,
|
||||||
|
'text-offset': [0, 0.5],
|
||||||
|
'text-anchor': 'top'
|
||||||
|
},
|
||||||
|
paint: {
|
||||||
|
'text-color': '#000000'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove () {
|
||||||
|
this._removePolygons()
|
||||||
|
this._container.parentNode.removeChild(this._container)
|
||||||
|
this._map = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-100">
|
<div class="h-100">
|
||||||
<!-- 地图组件 -->
|
<!-- 地图组件 -->
|
||||||
<map-box ref="mapbox" :enableGuided="true" :enableFollow="true" :enblueScale="!$store.state.app.isWideScreen"
|
<map-box ref="mapbox" :showNofly="true" :enableGuided="true" :enableFollow="true" :enblueScale="!$store.state.app.isWideScreen"
|
||||||
@longPress="handleLongPress">
|
@longPress="handleLongPress">
|
||||||
<template #content>
|
<template #content>
|
||||||
<BatteryStatus :plane="plane" />
|
<BatteryStatus :plane="plane" />
|
||||||
|
Loading…
Reference in New Issue
Block a user