编辑地图优化
This commit is contained in:
parent
be3dd9f1e6
commit
25035ac4cf
@ -375,6 +375,7 @@ const MathPI = ref(Math.PI)
|
||||
|
||||
const equipmentList = ref([]) //用过的设备列表
|
||||
const open = (item, list) => {
|
||||
console.log(item)
|
||||
form.value = item
|
||||
form.value.layersNumber = item.dataList?.length || ''
|
||||
form.value.positionMapId = props.positionMapId
|
||||
|
@ -1314,8 +1314,11 @@ const handleInputEnd = () => {
|
||||
}
|
||||
//编辑节点成功
|
||||
const submitNodeSuccess = (form) => {
|
||||
let actualPoint = disposeEventPoint(form.locationX, form.locationY)
|
||||
form.locationDeepPx = Number(form.locationDeep) / 100 / imgBgObj.resolution
|
||||
form.locationWidePx = Number(form.locationWide) / 100 / imgBgObj.resolution
|
||||
form.actualLocationX = actualPoint.actualLocationX
|
||||
form.actualLocationY = actualPoint.actualLocationY
|
||||
state.allMapPointInfo[state.currentItemIndex] = form
|
||||
|
||||
//节点位置改变 通知路径里面的节点也改变
|
||||
@ -2218,7 +2221,19 @@ const resetDrawState = () => {
|
||||
state.currentDrawY = 0
|
||||
}
|
||||
|
||||
//开始框选绘制
|
||||
// 节流函数
|
||||
const throttle = (fn, delay) => {
|
||||
let lastTime = 0
|
||||
return function (...args) {
|
||||
const now = Date.now()
|
||||
if (now - lastTime >= delay) {
|
||||
lastTime = now
|
||||
return fn.apply(this, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 优化后的框选相关函数
|
||||
const startDrawSelection = (event) => {
|
||||
if (
|
||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||
@ -2227,20 +2242,20 @@ const startDrawSelection = (event) => {
|
||||
toolbarSwitchType.value == 'generateLine' ||
|
||||
toolbarSwitchType.value === 'bulkDelete'
|
||||
) {
|
||||
const x = disposeEventPoints(event).x
|
||||
const y = disposeEventPoints(event).y
|
||||
const { x, y } = disposeEventPoints(event)
|
||||
|
||||
// 确保点击在背景区域内
|
||||
if (x >= 0 && x <= imgBgObj.width && y >= 0 && y <= imgBgObj.height) {
|
||||
state.drawSelectionAreaShow = true
|
||||
state.drawSelectionStartPoint = { x: x, y: y }
|
||||
state.drawSelectionAreaBox = { x: x, y: y, width: 0, height: 0 }
|
||||
state.drawSelectionStartPoint = { x, y }
|
||||
state.drawSelectionAreaBox = { x, y, width: 0, height: 0 }
|
||||
}
|
||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
// 更新框选区域
|
||||
const updateDrawSelection = (event) => {
|
||||
|
||||
// 使用节流优化更新框选区域
|
||||
const updateDrawSelection = throttle((event) => {
|
||||
if (
|
||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||
toolbarSwitchType.value === 'createRegion' ||
|
||||
@ -2249,31 +2264,36 @@ const updateDrawSelection = (event) => {
|
||||
toolbarSwitchType.value === 'bulkDelete'
|
||||
) {
|
||||
if (state.drawSelectionAreaShow) {
|
||||
const x = disposeEventPoints(event).x
|
||||
const y = disposeEventPoints(event).y
|
||||
const { x, y } = disposeEventPoints(event)
|
||||
|
||||
state.drawSelectionAreaBox = {
|
||||
x: Math.min(state.drawSelectionStartPoint.x, x),
|
||||
y: Math.min(state.drawSelectionStartPoint.y, y),
|
||||
width: Math.abs(Number(x) - Number(state.drawSelectionStartPoint.x)),
|
||||
height: Math.abs(Number(y) - Number(state.drawSelectionStartPoint.y))
|
||||
}
|
||||
// 使用 requestAnimationFrame 优化渲染
|
||||
requestAnimationFrame(() => {
|
||||
state.drawSelectionAreaBox = {
|
||||
x: Math.min(state.drawSelectionStartPoint.x, x),
|
||||
y: Math.min(state.drawSelectionStartPoint.y, y),
|
||||
width: Math.abs(x - state.drawSelectionStartPoint.x),
|
||||
height: Math.abs(y - state.drawSelectionStartPoint.y)
|
||||
}
|
||||
})
|
||||
}
|
||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
if (toolbarSwitchType.value === 'clickDrawRoute') {
|
||||
// 实时绘制
|
||||
if (state.isDrawing) {
|
||||
const x = disposeEventPoints(event).x
|
||||
const y = disposeEventPoints(event).y
|
||||
const { x, y } = disposeEventPoints(event)
|
||||
|
||||
state.currentDrawX = x
|
||||
state.currentDrawY = y
|
||||
// 使用 requestAnimationFrame 优化渲染
|
||||
requestAnimationFrame(() => {
|
||||
state.currentDrawX = x
|
||||
state.currentDrawY = y
|
||||
})
|
||||
}
|
||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
//结束框选绘制
|
||||
}, 16) // 约60fps的更新频率
|
||||
|
||||
// 优化结束框选
|
||||
const endDrawSelection = (event) => {
|
||||
if (toolbarSwitchType.value === 'clickDrawRoute') {
|
||||
if (state.isDrawing) {
|
||||
@ -2331,8 +2351,11 @@ const endDrawSelection = (event) => {
|
||||
endPointSortNum: endPoint.sortNum
|
||||
}
|
||||
|
||||
state.mapRouteList.push(newRoute)
|
||||
addEditHistory()
|
||||
// 使用 requestAnimationFrame 优化渲染
|
||||
requestAnimationFrame(() => {
|
||||
state.mapRouteList.push(newRoute)
|
||||
addEditHistory()
|
||||
})
|
||||
}
|
||||
}
|
||||
resetDrawState()
|
||||
@ -2340,6 +2363,7 @@ const endDrawSelection = (event) => {
|
||||
event.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||
toolbarSwitchType.value === 'createRegion' ||
|
||||
@ -2347,45 +2371,18 @@ const endDrawSelection = (event) => {
|
||||
toolbarSwitchType.value === 'generateLine' ||
|
||||
toolbarSwitchType.value === 'bulkDelete'
|
||||
) {
|
||||
state.drawSelectionAreaShow = false
|
||||
state.allDrawSelectionAreaBox.push({ ...state.drawSelectionAreaBox })
|
||||
state.drawSelectionAreaBox = { x: 0, y: 0, width: 0, height: 0 }
|
||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||
return
|
||||
// 使用 requestAnimationFrame 优化渲染
|
||||
requestAnimationFrame(() => {
|
||||
state.drawSelectionAreaShow = false
|
||||
if (state.drawSelectionAreaBox.width > 0 && state.drawSelectionAreaBox.height > 0) {
|
||||
state.allDrawSelectionAreaBox.push({ ...state.drawSelectionAreaBox })
|
||||
}
|
||||
state.drawSelectionAreaBox = { x: 0, y: 0, width: 0, height: 0 }
|
||||
})
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
// 找到最近的点
|
||||
const findClosestPoint = (x, y) => {
|
||||
const list = state.allMapPointInfo
|
||||
if (!Array.isArray(list) || list.length === 0) return null
|
||||
|
||||
const searchRadius = 100
|
||||
let minDistance = Infinity
|
||||
let closestIndex = null
|
||||
|
||||
// 使用空间分区优化:先进行粗略筛选
|
||||
const potentialPoints = list.filter((point, index) => {
|
||||
if (!point?.locationX || !point?.locationY) return false
|
||||
const dx = Math.abs(point.locationX - x)
|
||||
const dy = Math.abs(point.locationY - y)
|
||||
return dx <= searchRadius && dy <= searchRadius
|
||||
})
|
||||
|
||||
// 在筛选后的点中找最近的
|
||||
potentialPoints.forEach((point, i) => {
|
||||
const dx = point.locationX - x
|
||||
const dy = point.locationY - y
|
||||
const distance = Math.sqrt(dx * dx + dy * dy)
|
||||
const captureRadius = point.locationWide || 10
|
||||
|
||||
if (distance < minDistance && distance < captureRadius) {
|
||||
minDistance = distance
|
||||
closestIndex = list.findIndex((p) => p.id === point.id)
|
||||
}
|
||||
})
|
||||
|
||||
return closestIndex
|
||||
}
|
||||
//点击区域
|
||||
const clickDrawSelectionArea = () => {
|
||||
let points = state.allMapPointInfo
|
||||
@ -2552,47 +2549,61 @@ const clickDrawSelectionArea = () => {
|
||||
}
|
||||
//生成直线 选择完成开始点和结束点
|
||||
const GenerateStraightLinesSubmit = (pointList, form) => {
|
||||
const list = mapPointsToLine(pointList, form.startPointId, form.endPointId)
|
||||
const idNameMap = {}
|
||||
list.forEach((item) => {
|
||||
idNameMap[item.id] = item
|
||||
// 使用 requestAnimationFrame 优化渲染
|
||||
requestAnimationFrame(() => {
|
||||
const list = mapPointsToLine(pointList, form.startPointId, form.endPointId)
|
||||
const idNameMap = new Map(list.map((item) => [item.id, item]))
|
||||
|
||||
// 批量更新点位
|
||||
const updatedPoints = state.allMapPointInfo.map((item) => {
|
||||
if (idNameMap.has(item.id)) {
|
||||
const newPoint = idNameMap.get(item.id)
|
||||
const actualPoint = disposeEventPoint(newPoint.locationX, newPoint.locationY)
|
||||
return {
|
||||
...item,
|
||||
locationX: newPoint.locationX,
|
||||
locationY: newPoint.locationY,
|
||||
actualLocationX: actualPoint.actualLocationX,
|
||||
actualLocationY: actualPoint.actualLocationY
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
|
||||
// 批量更新路线
|
||||
const updatedRoutes = state.mapRouteList.map((item) => {
|
||||
const startPoint = idNameMap.get(item.startingPointId)
|
||||
const endPoint = idNameMap.get(item.endPointId)
|
||||
|
||||
if (startPoint || endPoint) {
|
||||
const result = { ...item }
|
||||
|
||||
if (startPoint) {
|
||||
const actualStartPoint = disposeEventPoint(startPoint.locationX, startPoint.locationY)
|
||||
result.startPointX = startPoint.locationX
|
||||
result.startPointY = startPoint.locationY
|
||||
result.actualStartPointX = actualStartPoint.actualLocationX
|
||||
result.actualStartPointY = actualStartPoint.actualLocationY
|
||||
}
|
||||
|
||||
if (endPoint) {
|
||||
const actualEndPoint = disposeEventPoint(endPoint.locationX, endPoint.locationY)
|
||||
result.endPointX = endPoint.locationX
|
||||
result.endPointY = endPoint.locationY
|
||||
result.actualEndPointX = actualEndPoint.actualLocationX
|
||||
result.actualEndPointY = actualEndPoint.actualLocationY
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
return item
|
||||
})
|
||||
|
||||
// 批量更新状态
|
||||
state.allMapPointInfo = updatedPoints
|
||||
state.mapRouteList = updatedRoutes
|
||||
addEditHistory()
|
||||
})
|
||||
// 遍历第二个数组,更新 name
|
||||
state.allMapPointInfo.forEach((item) => {
|
||||
if (idNameMap[item.id]) {
|
||||
let actualPoint = disposeEventPoint(
|
||||
idNameMap[item.id].locationX,
|
||||
idNameMap[item.id].locationY
|
||||
)
|
||||
item.locationX = idNameMap[item.id].locationX
|
||||
item.locationY = idNameMap[item.id].locationY
|
||||
item.actualLocationX = actualPoint.actualLocationX
|
||||
item.actualLocationY = actualPoint.actualLocationY
|
||||
}
|
||||
})
|
||||
state.mapRouteList.forEach((item) => {
|
||||
if (idNameMap[item.startingPointId]) {
|
||||
let actualPoint = disposeEventPoint(
|
||||
idNameMap[item.startingPointId].locationX,
|
||||
idNameMap[item.startingPointId].locationY
|
||||
)
|
||||
item.startPointX = idNameMap[item.startingPointId].locationX
|
||||
item.startPointY = idNameMap[item.startingPointId].locationY
|
||||
item.actualStartPointX = actualPoint.actualLocationX
|
||||
item.actualStartPointY = actualPoint.actualLocationY
|
||||
}
|
||||
if (idNameMap[item.endPointId]) {
|
||||
let actualPoint = disposeEventPoint(
|
||||
idNameMap[item.endPointId].locationX,
|
||||
idNameMap[item.endPointId].locationY
|
||||
)
|
||||
item.endPointX = idNameMap[item.endPointId].locationX
|
||||
item.endPointY = idNameMap[item.endPointId].locationY
|
||||
item.actualEndPointX = actualPoint.actualLocationX
|
||||
item.actualEndPointY = actualPoint.actualLocationY
|
||||
}
|
||||
})
|
||||
addEditHistory()
|
||||
}
|
||||
//去重
|
||||
const deduplicateArrayById = (arr) => {
|
||||
@ -3695,6 +3706,81 @@ const checkRouteDuplicate = (startPoint, endPoint, routeList) => {
|
||||
(route.startingPointId === endPoint.id && route.endPointId === startPoint.id)
|
||||
)
|
||||
}
|
||||
|
||||
// 空间分区优化
|
||||
const GRID_SIZE = 200 // 网格大小
|
||||
const gridMap = new Map() // 网格映射
|
||||
|
||||
// 获取点所在的网格坐标
|
||||
const getGridKey = (x, y) => {
|
||||
const gridX = Math.floor(x / GRID_SIZE)
|
||||
const gridY = Math.floor(y / GRID_SIZE)
|
||||
return `${gridX},${gridY}`
|
||||
}
|
||||
|
||||
// 更新网格数据
|
||||
const updateGridMap = (points) => {
|
||||
gridMap.clear()
|
||||
points.forEach((point, index) => {
|
||||
if (!point?.locationX || !point?.locationY) return
|
||||
const key = getGridKey(point.locationX, point.locationY)
|
||||
if (!gridMap.has(key)) {
|
||||
gridMap.set(key, [])
|
||||
}
|
||||
gridMap.get(key).push({ point, index })
|
||||
})
|
||||
}
|
||||
|
||||
// 获取指定网格及其相邻网格中的点
|
||||
const getNearbyPoints = (x, y) => {
|
||||
const centerKey = getGridKey(x, y)
|
||||
const [centerX, centerY] = centerKey.split(',').map(Number)
|
||||
const nearbyPoints = []
|
||||
|
||||
// 检查中心网格及其相邻网格
|
||||
for (let dx = -1; dx <= 1; dx++) {
|
||||
for (let dy = -1; dy <= 1; dy++) {
|
||||
const key = `${centerX + dx},${centerY + dy}`
|
||||
const points = gridMap.get(key)
|
||||
if (points) {
|
||||
nearbyPoints.push(...points)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nearbyPoints
|
||||
}
|
||||
|
||||
// 优化后的findClosestPoint函数
|
||||
const findClosestPoint = (x, y) => {
|
||||
const list = state.allMapPointInfo
|
||||
if (!Array.isArray(list) || list.length === 0) return null
|
||||
|
||||
// 更新网格数据
|
||||
updateGridMap(list)
|
||||
|
||||
const searchRadius = 100
|
||||
let minDistance = Infinity
|
||||
let closestIndex = null
|
||||
|
||||
// 获取附近的点
|
||||
const nearbyPoints = getNearbyPoints(x, y)
|
||||
|
||||
// 在附近的点中找最近的
|
||||
for (const { point, index } of nearbyPoints) {
|
||||
const dx = point.locationX - x
|
||||
const dy = point.locationY - y
|
||||
const distance = Math.sqrt(dx * dx + dy * dy)
|
||||
const captureRadius = point.locationWide || 10
|
||||
|
||||
if (distance < minDistance && distance < captureRadius) {
|
||||
minDistance = distance
|
||||
closestIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
return closestIndex
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
91
src/views/mapPage/realTimeMap/格式.md
Normal file
91
src/views/mapPage/realTimeMap/格式.md
Normal file
@ -0,0 +1,91 @@
|
||||
<!-- ```
|
||||
{
|
||||
labelType: 'wayPoint', //类型 路径点wayPoint 库位点locationPoint 设备点devicePoint 停车点parkingPoint 区域变更点areaPoint 等待点waitPoint 文字text
|
||||
mapId: '', //地图id
|
||||
x: 100, //left
|
||||
y: 100, //top
|
||||
h: 100, //高
|
||||
w: 100, //宽
|
||||
angle: 13, //旋转角度
|
||||
draggable: true, //是否可以拖动
|
||||
resizable: true, //是否可以调整大小
|
||||
rotatable: true, //是否可以旋转
|
||||
lockAspectRatio: true, //是否保持横纵比
|
||||
img: 'https://sys.znkjfw.com/imgs/process/%E8%AF%B7%E5%81%87.png',
|
||||
text: '', //文字
|
||||
fontColor: '', //文字颜色
|
||||
fontType: '', //文字类型
|
||||
fontFamily: '' //字体类型
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
1.普通节点 dataJson 不传数据
|
||||
|
||||
|
||||
2.库位点 dataJson 数据格式:
|
||||
[
|
||||
{
|
||||
"id": 1881176241622024200, //库位id - 编辑的时候会有需要传过来 新增的时候没有则不传
|
||||
"laneId": 1881177420829642800, //线库id - 编辑的时候有就传过来 新增的时候没有就不传
|
||||
"laneName": "测试33", //线库名称 - 编辑的时候有就传过来 新增的时候没有就不传
|
||||
"locationX": "2", //库位坐标x轴 - 编辑的时候有就传过来 新增的时候不用传
|
||||
"locationY": "7", //库位坐标y轴 - 编辑的时候有就传过来 新增的时候不用传
|
||||
"locationWide": 10, //宽度 - 编辑的时候有就传过来 新增的时候需要传
|
||||
"locationDeep": 10, //高度 - 编辑的时候有就传过来 新增的时候需要传
|
||||
"direction": 1, //库位方向(1:单向、2:双向、3:三向、4:四向) 编辑的时候有就传过来 新增的时候需要传
|
||||
"inDirection": 1, //进入方向(0:尾入、1:头入) 编辑的时候有就传过来 新增的时候需要传
|
||||
"outDirection": 1, //离开方向(0:尾出、1:头出) 编辑的时候有就传过来 新增的时候需要传
|
||||
"locationStorey": 3, //层数 编辑的时候有就传过来 新增的时候需要传
|
||||
"mapId": 1, //地图id 编辑的时候有就传过来 新增的时候不需要传
|
||||
"mapItemId": 1881176241622024200 //地图子表id 编辑的时候有就传过来 新增的时候不需要传
|
||||
},
|
||||
{
|
||||
"id": 1881176241622024200,
|
||||
"laneId": 1881177420829642800,
|
||||
"laneName": "测试33",
|
||||
"locationX": "2",
|
||||
"locationY": "7",
|
||||
"locationWide": 10,
|
||||
"locationDeep": 10,
|
||||
"direction": 1,
|
||||
"inDirection": 1,
|
||||
"outDirection": 1,
|
||||
"locationStorey": 3,
|
||||
"mapId": 1,
|
||||
"mapItemId": 1881176241622024200
|
||||
}
|
||||
]
|
||||
|
||||
3.设备点 dataJson 数据格式:
|
||||
{
|
||||
"id": 1881176241622024200, //设备id - 新增编辑都需要传 - 根据选择的设备获取到
|
||||
"locationX": "2", //库位坐标x轴 - 编辑的时候有就传过来 新增的时候不用传
|
||||
"locationY": "7", //库位坐标y轴 - 编辑的时候有就传过来 新增的时候不用传
|
||||
"locationWide": 10, //宽度 - 编辑的时候有就传过来 新增的时候需要传
|
||||
"locationDeep": 10, //高度 - 编辑的时候有就传过来 新增的时候需要传
|
||||
"mapId": 1, //地图id 编辑的时候有就传过来 新增的时候不需要传
|
||||
"mapItemId": 1881176241622024200 //地图子表id 编辑的时候有就传过来 新增的时候不需要传
|
||||
}
|
||||
4.停车点 dataJson 数据格式:
|
||||
|
||||
{
|
||||
"id": 1881176241622024200, //停车点id - 编辑的时候会有需要传过来 新增的时候没有则不传
|
||||
"locationX": "2", //库位坐标x轴 - 编辑的时候有就传过来 新增的时候不用传
|
||||
"locationY": "7", //库位坐标y轴 - 编辑的时候有就传过来 新增的时候不用传
|
||||
"locationWide": 10, //宽度 - 编辑的时候有就传过来 新增的时候需要传
|
||||
"locationDeep": 10, //高度 - 编辑的时候有就传过来 新增的时候需要传
|
||||
"direction": 1, //库位方向(1:单向、2:双向、3:三向、4:四向) 编辑的时候有就传过来 新增的时候需要传
|
||||
"inDirection": 1, //进入方向(0:尾入、1:头入) 编辑的时候有就传过来 新增的时候需要传
|
||||
"outDirection": 1, //离开方向(0:尾出、1:头出) 编辑的时候有就传过来 新增的时候需要传
|
||||
"mapId": 1, //地图id 编辑的时候有就传过来 新增的时候不需要传
|
||||
"mapItemId": 1881176241622024200 //地图子表id 编辑的时候有就传过来 新增的时候不需要传
|
||||
},
|
||||
|
||||
5.路径点 dataJson 不传数据
|
||||
|
||||
6.等待点 dataJson 不传数据
|
||||
|
||||
|
||||
``` -->
|
Loading…
Reference in New Issue
Block a user