编辑地图优化

This commit is contained in:
yyy 2025-06-09 15:45:02 +08:00
parent be3dd9f1e6
commit 25035ac4cf
3 changed files with 281 additions and 103 deletions

View File

@ -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

View File

@ -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>

View 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 不传数据
``` -->