1、增加路线右击自定义菜单,按照开始点和结束点自动生成左上、右下、右上、左下直角拐角

2、点击地图显示实际位置改为点击到节点则按照节点的位置展示
This commit is contained in:
yyy 2025-07-01 15:24:39 +08:00
parent 8efb54dd52
commit cd17472173

View File

@ -497,6 +497,7 @@
<!-- 节点合集 --> <!-- 节点合集 -->
<div <div
@mousedown="startFromPoint(index, $event)" @mousedown="startFromPoint(index, $event)"
@click.stop="handleNodeClick(item)"
:style="{ width: item.locationWidePx + 'px', height: item.locationDeepPx + 'px' }" :style="{ width: item.locationWidePx + 'px', height: item.locationDeepPx + 'px' }"
> >
<!-- 1 路径点 --> <!-- 1 路径点 -->
@ -700,6 +701,7 @@
:stroke="curve.isSelected ? '#f48924' : '#2d72d9'" :stroke="curve.isSelected ? '#f48924' : '#2d72d9'"
:stroke-width="state.routeWidthForm.routeWidth" :stroke-width="state.routeWidthForm.routeWidth"
@click="(e) => handleChooseRoute(curve, index, 'line', e)" @click="(e) => handleChooseRoute(curve, index, 'line', e)"
@contextmenu="handleCurveContextMenu(curve, index, $event)"
/> />
<text <text
style="user-select: none" style="user-select: none"
@ -724,6 +726,7 @@
:stroke-width="state.routeWidthForm.routeWidth" :stroke-width="state.routeWidthForm.routeWidth"
fill="none" fill="none"
@click="handleChooseRoute(curve, index)" @click="handleChooseRoute(curve, index)"
@contextmenu="handleCurveContextMenu(curve, index, $event)"
/> />
<text <text
style="user-select: none" style="user-select: none"
@ -766,7 +769,12 @@
</template> </template>
</template> </template>
<!-- 控制点circle统一渲染保证层级最高 --> <!-- 控制点circle统一渲染保证层级最高 -->
<template v-if="state.currentDragTarget.index !== null"> <template
v-if="
state.currentDragTarget.index !== null &&
state.mapRouteList[state.currentDragTarget.index].method !== 0
"
>
<circle <circle
id="startCircle" id="startCircle"
:cx="state.mapRouteList[state.currentDragTarget.index].beginControlX" :cx="state.mapRouteList[state.currentDragTarget.index].beginControlX"
@ -958,7 +966,7 @@
:imgBgObj="imgBgObj" :imgBgObj="imgBgObj"
@submit-batch-copying-form-success="submitBatchCopyingFormSuccess" @submit-batch-copying-form-success="submitBatchCopyingFormSuccess"
/> />
<!-- 节点右击菜单 -->
<div <div
v-if="state.contextMenu.visible" v-if="state.contextMenu.visible"
class="context-menu" class="context-menu"
@ -974,6 +982,24 @@
>生成检测点</div >生成检测点</div
> >
</div> </div>
<!-- 曲线右击菜单 -->
<div
v-if="state.curveContextMenu.visible"
class="context-menu"
:style="{ left: state.curveContextMenu.x + 'px', top: state.curveContextMenu.y + 'px' }"
@click.stop
>
<div class="context-menu-item" @click="deleteCurveRoute">删除</div>
<div class="context-menu-item" @click="contextMenuEditRoute">编辑路线</div>
<template
v-for="dir in getAvailableRightAngleDirections(state.curveContextMenu.currentCurve)"
:key="dir"
>
<div class="context-menu-item" @click="() => setCurveRightAngle(dir)">
{{ rightAngleDirectionLabel(dir) }}
</div>
</template>
</div>
</div> </div>
</template> </template>
@ -1742,6 +1768,13 @@ const state = reactive({
y: 0, // y y: 0, // y
currentItem: null, // currentItem: null, //
currentIndex: -1 // currentIndex: -1 //
},
curveContextMenu: {
visible: false,
x: 0,
y: 0,
currentCurve: null,
currentIndex: -1
} }
}) })
@ -2120,6 +2153,7 @@ const handleContextMenu = (item, index, event) => {
state.contextMenu.y = event.clientY state.contextMenu.y = event.clientY
state.contextMenu.currentItem = item state.contextMenu.currentItem = item
state.contextMenu.currentIndex = index state.contextMenu.currentIndex = index
state.currentItemIndex = index
} }
// //
@ -4347,6 +4381,129 @@ const findClosestPoint = (x, y) => {
return closestIndex return closestIndex
} }
// 线
const handleCurveContextMenu = (curve, index, event) => {
event.preventDefault()
state.curveContextMenu.visible = true
state.curveContextMenu.x = event.clientX
state.curveContextMenu.y = event.clientY
state.curveContextMenu.currentCurve = curve
state.curveContextMenu.currentIndex = index
state.currentDragTarget.index = index
}
// 线
const hideCurveContextMenu = () => {
state.curveContextMenu.visible = false
state.curveContextMenu.currentIndex = -1
}
// 线UI
const deleteCurveRoute = () => {
if (state.currentDragTarget.index !== null) {
state.mapRouteList.splice(state.currentDragTarget.index, 1)
state.currentDragTarget.index = null
}
addEditHistory()
hideCurveContextMenu()
}
// 线
window.addEventListener('click', (e) => {
if (state.curveContextMenu.visible) {
const menu = document.querySelector('.context-menu')
if (menu && !menu.contains(e.target)) {
hideCurveContextMenu()
}
}
})
//
function getRightAngleControlPoints(direction, start, end, offset = 0) {
let corner
if (direction === 'leftTop') {
corner = { x: Math.min(start.x, end.x), y: Math.min(start.y, end.y) }
} else if (direction === 'rightBottom') {
corner = { x: Math.max(start.x, end.x), y: Math.max(start.y, end.y) }
} else if (direction === 'leftBottom') {
corner = { x: Math.min(start.x, end.x), y: Math.max(start.y, end.y) }
} else if (direction === 'rightTop') {
corner = { x: Math.max(start.x, end.x), y: Math.min(start.y, end.y) }
} else {
corner = { x: end.x, y: start.y }
}
//
const getUnit = (from, to) => {
const dx = from.x - to.x
const dy = from.y - to.y
const len = Math.sqrt(dx * dx + dy * dy) || 1
return { x: dx / len, y: dy / len }
}
// /offset
const u1 = getUnit(corner, start)
const u2 = getUnit(corner, end)
const beginControl = { x: corner.x + u1.x * offset, y: corner.y + u1.y * offset }
const endControl = { x: corner.x + u2.x * offset, y: corner.y + u2.y * offset }
return { beginControl, endControl }
}
// 线
function setCurveRightAngle(direction) {
const curve = state.curveContextMenu.currentCurve
if (!curve) return
const start = { x: curve.startPointX, y: curve.startPointY }
const end = { x: curve.endPointX, y: curve.endPointY }
const { beginControl, endControl } = getRightAngleControlPoints(direction, start, end)
curve.beginControlX = beginControl.x
curve.beginControlY = beginControl.y
curve.endControlX = endControl.x
curve.endControlY = endControl.y
curve.method = 1
hideCurveContextMenu()
}
//
function getAvailableRightAngleDirections(curve) {
if (!curve) return []
const sx = curve.startPointX,
sy = curve.startPointY,
ex = curve.endPointX,
ey = curve.endPointY
const dx = ex - sx
const dy = ey - sy
if (dx === 0 || dy === 0) return []
if (dx * dy > 0) return ['leftBottom', 'rightTop']
if (dx * dy < 0) return ['leftTop', 'rightBottom']
return []
}
// label
function rightAngleDirectionLabel(dir) {
switch (dir) {
case 'rightTop':
return '右上直角拐角'
case 'rightBottom':
return '右下直角拐角'
case 'leftTop':
return '左上直角拐角'
case 'leftBottom':
return '左下直角拐角'
default:
return ''
}
}
//线
const contextMenuEditRoute = () => {
removeEventListener() //
let item = state.mapRouteList[state.currentDragTarget.index]
editMapRouteDialogRef.value.open(JSON.parse(JSON.stringify(item)))
}
// locationX/locationY
function handleNodeClick(item) {
state.actualLocation.x = item.actualLocationX ? Number(item.actualLocationX).toFixed(3) : ''
state.actualLocation.y = item.actualLocationY ? Number(item.actualLocationY).toFixed(3) : ''
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>