This commit is contained in:
xhf 2025-02-22 17:06:20 +08:00
commit 6f0db9c934
5 changed files with 941 additions and 668 deletions

View File

@ -4,7 +4,7 @@ NODE_ENV=development
VITE_DEV=true VITE_DEV=true
# 请求路径 # 请求路径
VITE_BASE_URL='http://192.168.0.74:48080' VITE_BASE_URL='http://192.168.0.172:48080'
# VITE_BASE_URL='http://192.168.0.189:48080' # VITE_BASE_URL='http://192.168.0.189:48080'
# 文件上传类型server - 后端上传, client - 前端直连上传,仅支持 S3 服务 # 文件上传类型server - 后端上传, client - 前端直连上传,仅支持 S3 服务

View File

@ -229,10 +229,10 @@ const open = (item, list) => {
console.log(item) console.log(item)
form.value = item form.value = item
form.value.layersNumber = item.dataList.length || '' form.value.layersNumber = item.dataList.length || ''
form.value.deviceId = item.deviceId || item.dataObj.id || '' form.value.deviceId = item?.deviceId || item?.dataObj?.id || ''
form.value.positionMapId = props.positionMapId form.value.positionMapId = props.positionMapId
equipmentList.value = list equipmentList.value = list
if (item.dataObj.deviceType) { if (item?.dataObj?.deviceType) {
deviceInfo.value.deviceType = item.dataObj.deviceType || '' deviceInfo.value.deviceType = item.dataObj.deviceType || ''
getDeviceList() getDeviceList()
} else { } else {

View File

@ -2,7 +2,12 @@
<template> <template>
<div :style="wrapperStyle" class="vue-ruler-wrapper" onselectstart="return false;" ref="el"> <div :style="wrapperStyle" class="vue-ruler-wrapper" onselectstart="return false;" ref="el">
<section> <section>
<div ref="horizontalRuler" class="vue-ruler-h" @mousedown.stop="horizontalDragRuler"> <div
ref="horizontalRuler"
class="vue-ruler-h"
@mousedown.stop="horizontalDragRuler"
:style="{ width: width + 'px' }"
>
<span <span
v-for="(item, index) in xScale" v-for="(item, index) in xScale"
:key="index" :key="index"
@ -11,7 +16,12 @@
>{{ item.id }}</span >{{ item.id }}</span
> >
</div> </div>
<div ref="verticalRuler" class="vue-ruler-v" @mousedown.stop="verticalDragRuler"> <div
ref="verticalRuler"
class="vue-ruler-v"
@mousedown.stop="verticalDragRuler"
:style="{ height: height + 'px' }"
>
<span <span
v-for="(item, index) in yScale" v-for="(item, index) in yScale"
:key="index" :key="index"
@ -82,6 +92,12 @@ const props = defineProps({
type: Number, type: Number,
default: 100, default: 100,
validator: (val) => val % 10 === 0 validator: (val) => val % 10 === 0
},
width: {
type: Number
},
height: {
type: Number
} }
}) })
@ -166,12 +182,10 @@ onBeforeUnmount(() => {
off(document, 'mouseup', dottedLineUp) off(document, 'mouseup', dottedLineUp)
off(window, 'resize', windowResize) off(window, 'resize', windowResize)
}) })
//function
const init = () => { const init = () => {
box() box()
scaleCalc() scaleCalc()
} }
const windowResize = () => { const windowResize = () => {
xScale.value = [{ id: 0 }] xScale.value = [{ id: 0 }]
yScale.value = [{ id: 0 }] yScale.value = [{ id: 0 }]
@ -193,8 +207,10 @@ const box = () => {
getCalcRevise(xScale.value, contentLeft) getCalcRevise(xScale.value, contentLeft)
getCalcRevise(yScale.value, contentTop) getCalcRevise(yScale.value, contentTop)
} }
windowWidth.value = document.documentElement.clientWidth - leftSpacing // windowWidth.value = document.documentElement.clientWidth - leftSpacing
windowHeight.value = document.documentElement.clientHeight - topSpacing - 80 // windowHeight.value = document.documentElement.clientHeight - topSpacing - 80
windowWidth.value = props.width + 18
windowHeight.value = props.height + 18
rulerWidth = verticalRuler.value.clientWidth rulerWidth = verticalRuler.value.clientWidth
rulerHeight = horizontalRuler.value.clientHeight rulerHeight = horizontalRuler.value.clientHeight
} }
@ -204,8 +220,8 @@ const setSpacing = () => {
} }
// //
const scaleCalc = () => { const scaleCalc = () => {
getCalc(xScale.value, windowWidth.value) getCalc(xScale.value, props.width)
getCalc(yScale.value, windowHeight.value) getCalc(yScale.value, props.height)
} }
// //
@ -360,7 +376,7 @@ const dragVerticalLine = (id) => {
} }
.vue-ruler-h { .vue-ruler-h {
width: calc(100% - 18px); // width: calc(100% - 18px);
background-color: #333; background-color: #333;
height: 18px; height: 18px;
left: 18px; left: 18px;
@ -371,7 +387,7 @@ const dragVerticalLine = (id) => {
.vue-ruler-v { .vue-ruler-v {
width: 18px; width: 18px;
height: 85vh; // height: 85vh;
top: 18px; top: 18px;
opacity: 0.6; opacity: 0.6;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAyCAMAAABmvHtTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRFMzMzAAAA////BqjYlAAAACBJREFUeNpiYGBEBwwMTGiAakI0NX7U9aOuHyGuBwgwAH6bBkAR6jkzAAAAAElFTkSuQmCC) background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAyCAMAAABmvHtTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRFMzMzAAAA////BqjYlAAAACBJREFUeNpiYGBEBwwMTGiAakI0NX7U9aOuHyGuBwgwAH6bBkAR6jkzAAAAAElFTkSuQmCC)

View File

@ -1,4 +1,5 @@
<template> <template>
<div class="edit-map-page">
<div class="top-tool"> <div class="top-tool">
<div class="top-tool-list"> <div class="top-tool-list">
<div v-for="item in state.topToolList" :key="item.switchType" class="top-tool-item"> <div v-for="item in state.topToolList" :key="item.switchType" class="top-tool-item">
@ -202,6 +203,14 @@
</div> </div>
<div class="map-container" ref="mapContainer" :style="{ cursor: state.cursorStyle }"> <div class="map-container" ref="mapContainer" :style="{ cursor: state.cursorStyle }">
<map-scale-tool
v-if="imgBgObj.height && imgBgObj.width"
@input="input"
:value="presetLine"
:step-length="50"
:height="imgBgObj.height"
:width="imgBgObj.width"
>
<div <div
class="map-bg" class="map-bg"
:style="{ :style="{
@ -240,12 +249,14 @@
@resizestop="(x, y, width, height) => resizeEnd(x, y, width, height, item, index)" @resizestop="(x, y, width, height) => resizeEnd(x, y, width, height, item, index)"
@activated="() => activatedHandle(item, index)" @activated="() => activatedHandle(item, index)"
@deactivated="deactivatedHandle" @deactivated="deactivatedHandle"
:draggable="item.draggable && !state.prohibitedOperation" :draggable="!state.prohibitedOperation && item.draggable"
:resizable="item.resizable && !state.prohibitedOperation" :resizable="!state.prohibitedOperation && item.resizable"
:rotatable="item.rotatable && !state.prohibitedOperation" :rotatable="!state.prohibitedOperation && item.rotatable"
:lock-aspect-ratio="item.lockAspectRatio" :lock-aspect-ratio="item.lockAspectRatio"
style="border: none; z-index: 999" style="border: none; z-index: 999"
> >
<!-- 节点合集 -->
<div @mousedown="startFromPoint(index, $event)">
<!-- 1 路径点 --> <!-- 1 路径点 -->
<div <div
v-if="item.type === 1 && item.layerSelectionShow" v-if="item.type === 1 && item.layerSelectionShow"
@ -327,6 +338,7 @@
> >
{{ item.text }} {{ item.text }}
</div> </div>
</div>
</VueDragResizeRotate> </VueDragResizeRotate>
<div v-if="imgBgObj.width && imgBgObj.height"> <div v-if="imgBgObj.width && imgBgObj.height">
@ -334,8 +346,20 @@
:width="imgBgObj.width" :width="imgBgObj.width"
:height="imgBgObj.height" :height="imgBgObj.height"
style="position: absolute; top: 0; left: 0; z-index: 9" style="position: absolute; top: 0; left: 0; z-index: 9"
id="svgId"
> >
<template v-for="(curve, index) in state.mapRouteList" :key="index"> <template v-for="(curve, index) in state.mapRouteList" :key="index">
<!-- 实时绘制当前直线 -->
<line
v-if="state.isDrawing && toolbarSwitchType === 'clickDrawRoute'"
:x1="Number(state.startDrawPoint.locationX)"
:y1="Number(state.startDrawPoint.locationY)"
:x2="Number(state.currentDrawX)"
:y2="Number(state.currentDrawY)"
stroke="#00329F"
stroke-width="5"
/>
<!-- 直线 --> <!-- 直线 -->
<line <line
v-if="curve.method === 0" v-if="curve.method === 0"
@ -379,6 +403,7 @@
stroke-width="2" stroke-width="2"
/> />
<circle <circle
id="startCircle"
:cx="curve.beginControlX" :cx="curve.beginControlX"
:cy="curve.beginControlY" :cy="curve.beginControlY"
r="5" r="5"
@ -386,6 +411,7 @@
@mousedown="startDrag(curve, index, 'start')" @mousedown="startDrag(curve, index, 'start')"
/> />
<circle <circle
id="endCircle"
:cx="curve.endControlX" :cx="curve.endControlX"
:cy="curve.endControlY" :cy="curve.endControlY"
r="5" r="5"
@ -479,6 +505,7 @@
class="input-box-class" class="input-box-class"
/> />
</div> </div>
</map-scale-tool>
</div> </div>
<!-- 节点编辑 --> <!-- 节点编辑 -->
@ -525,6 +552,7 @@
ref="itemAreaManagementDialogRef" ref="itemAreaManagementDialogRef"
:positionMapId="imgBgObj.positionMapId" :positionMapId="imgBgObj.positionMapId"
/> />
</div>
</template> </template>
<script setup> <script setup>
@ -564,6 +592,11 @@ const currentIndex = ref(0) //用于记录是哪条历史记录的
const currentItemIndex = ref(-1) // const currentItemIndex = ref(-1) //
const allMapPointInfo = ref([]) // const allMapPointInfo = ref([]) //
const presetLine = ref([])
const input = (list) => {
presetLine.value = list
}
// //
const interfaceRefreshed = ref(true) const interfaceRefreshed = ref(true)
const resizeEnd = (locationX, locationY, w, h, item, index) => { const resizeEnd = (locationX, locationY, w, h, item, index) => {
@ -952,11 +985,17 @@ const state = reactive({
isActive: false isActive: false
}, },
{ {
switchType: 'drawRoute', switchType: 'clickDrawRoute',
name: '绘制路线', name: '绘制路线',
icon: 'ep:semi-select', icon: 'ep:semi-select',
isActive: false isActive: false
}, },
{
switchType: 'drawRoute',
name: '框选绘制',
icon: 'ep:semi-select',
isActive: false
},
{ {
switchType: 'editRoute', switchType: 'editRoute',
name: '编辑路线', name: '编辑路线',
@ -1003,7 +1042,11 @@ const state = reactive({
type: null type: null
}, // }, //
selectedCurve: '', // 线 selectedCurve: '', // 线
svgZIndex: 9999 startDrawPointIndex: -1, //
startDrawPoint: null,
isDrawing: false,
currentDrawX: 0,
currentDrawY: 0
}) })
const toolbarClick = (item) => { const toolbarClick = (item) => {
let type = item.switchType let type = item.switchType
@ -1060,7 +1103,10 @@ const toolbarClick = (item) => {
// //
if ( if (
toolbarSwitchType.value === 'ranging' || toolbarSwitchType.value === 'drawNodes' ||
toolbarSwitchType.value === 'editNode' ||
toolbarSwitchType.value === 'clickDrawRoute' ||
toolbarSwitchType.value === 'drawRoute' ||
toolbarSwitchType.value === 'createLineLibrary' || toolbarSwitchType.value === 'createLineLibrary' ||
toolbarSwitchType.value === 'createRegion' toolbarSwitchType.value === 'createRegion'
) { ) {
@ -1265,15 +1311,23 @@ const rotationFormSubmit = () => {
allHistoryList.value[currentIndex.value][currentItemIndex.value].angle = state.rotationForm.angle allHistoryList.value[currentIndex.value][currentItemIndex.value].angle = state.rotationForm.angle
} }
//
//
const startFromPoint = (index, event) => {
let list = allHistoryList.value[currentIndex.value]
const point = list[index]
state.startDrawPoint = point //
state.startDrawPointIndex = index
state.isDrawing = true
event.preventDefault() //
}
// //
const startDrawSelection = (event) => { const startDrawSelection = (event) => {
if ( if (
toolbarSwitchType.value !== 'createLineLibrary' && toolbarSwitchType.value === 'createLineLibrary' ||
toolbarSwitchType.value !== 'createRegion' && toolbarSwitchType.value === 'createRegion' ||
toolbarSwitchType.value !== 'drawRoute' toolbarSwitchType.value === 'drawRoute'
) ) {
return
const backgroundRect = mapBackgroundRef.value.getBoundingClientRect() const backgroundRect = mapBackgroundRef.value.getBoundingClientRect()
const x = disposeEventPoints(event).x const x = disposeEventPoints(event).x
@ -1286,42 +1340,151 @@ const startDrawSelection = (event) => {
state.drawSelectionAreaBox = { x: x, y: y, width: 0, height: 0 } state.drawSelectionAreaBox = { x: x, y: y, width: 0, height: 0 }
} }
// event.preventDefault() //
event.preventDefault() return
}
} }
// //
const updateDrawSelection = (event) => { const updateDrawSelection = (event) => {
if ( if (
toolbarSwitchType.value !== 'createLineLibrary' && toolbarSwitchType.value === 'createLineLibrary' ||
toolbarSwitchType.value !== 'createRegion' && toolbarSwitchType.value === 'createRegion' ||
toolbarSwitchType.value !== 'drawRoute' toolbarSwitchType.value === 'drawRoute'
) ) {
return
if (state.drawSelectionAreaShow) { if (state.drawSelectionAreaShow) {
const x = disposeEventPoints(event).x const x = disposeEventPoints(event).x
const y = disposeEventPoints(event).y const y = disposeEventPoints(event).y
state.drawSelectionAreaBox.width = Number(x) - Number(state.drawSelectionStartPoint.x) state.drawSelectionAreaBox = {
state.drawSelectionAreaBox.height = Number(y) - Number(state.drawSelectionStartPoint.y) 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))
} }
// }
event.preventDefault() event.preventDefault() //
return
}
if (toolbarSwitchType.value === 'clickDrawRoute') {
//
if (state.isDrawing) {
const x = disposeEventPoints(event).x
const y = disposeEventPoints(event).y
state.currentDrawX = x
state.currentDrawY = y
}
}
event.preventDefault() //
return
} }
// //
const endDrawSelection = (event) => { const endDrawSelection = (event) => {
if ( if (
toolbarSwitchType.value !== 'createLineLibrary' && toolbarSwitchType.value === 'createLineLibrary' ||
toolbarSwitchType.value !== 'createRegion' && toolbarSwitchType.value === 'createRegion' ||
toolbarSwitchType.value !== 'drawRoute' toolbarSwitchType.value === 'drawRoute'
) ) {
return
state.drawSelectionAreaShow = false state.drawSelectionAreaShow = false
state.allDrawSelectionAreaBox.push({ ...state.drawSelectionAreaBox }) state.allDrawSelectionAreaBox.push({ ...state.drawSelectionAreaBox })
state.drawSelectionAreaBox = { x: 0, y: 0, width: 0, height: 0 } state.drawSelectionAreaBox = { x: 0, y: 0, width: 0, height: 0 }
event.preventDefault() //
return
}
if (toolbarSwitchType.value === 'clickDrawRoute') {
if (state.isDrawing) {
//
const endPointIndex = findClosestPoint(state.currentDrawX, state.currentDrawY)
// if (endPointIndex !== null && endPointIndex !== state.startDrawPointIndex) {
event.preventDefault() let list = allHistoryList.value[currentIndex.value]
const endPoint = list[endPointIndex]
const newLine = {
startPointX: state.startDrawPoint.locationX,
startPointY: state.startDrawPoint.locationY,
endPointX: endPoint.locationX,
endPointY: endPoint.locationY
}
// 线
const isDuplicate = state.mapRouteList.some(
(line) =>
(line.startPointX === newLine.startPointX &&
line.startPointY === newLine.startPointY &&
line.endPointX === newLine.endPointX &&
line.endPointY === newLine.endPointY) ||
(line.startPointX === newLine.endPointX &&
line.startPointY === newLine.endPointY &&
line.endPointX === newLine.startPointX &&
line.endPointY === newLine.startPointY)
)
if (isDuplicate) {
message.warning('此路线已存在')
} else {
// 线
state.mapRouteList.push({
isSelected: false, //
startingPointId: state.startDrawPoint.id,
endPointId: endPoint.id,
startPointX: state.startDrawPoint.locationX, //
startPointY: state.startDrawPoint.locationY, //
endPointX: endPoint.locationX, //
endPointY: endPoint.locationY, //
actualStartPointX: state.startDrawPoint.actualLocationX, //x
actualStartPointY: state.startDrawPoint.actualLocationY, //y
actualEndPointX: endPoint.actualLocationX, //x
actualEndPointY: endPoint.actualLocationY, //y
actualBeginControlX: '', //x
actualBeginControlY: '', //y
actualEndControlX: '', //x
actualEndControlY: '', //y
beginControlX: 0, //x
beginControlY: 0, //y
endControlX: 0, //x
endControlY: 0, //y
expansionZoneFront: 0, //
expansionZoneAfter: 0, //
expansionZoneLeft: 0, //
expansionZoneRight: 0, //
method: 0, // 0.线 1.线2.线3.线 4.线
direction: 2, // 1. 2.,
forwardSpeedLimit: 1.5, //
reverseSpeedLimit: 0.4, //
toward: 0, // ( 0: 1: 2: 3:)
beginWidth: state.startDrawPoint.locationWide, //
beginHigh: state.startDrawPoint.locationDeep, //
endWidth: endPoint.locationWide, //
endHigh: endPoint.locationDeep //
})
}
}
//
state.startDrawPointIndex = -1 //
state.startDrawPoint = null
state.isDrawing = false
state.currentDrawX = 0
state.currentDrawY = 0
}
event.preventDefault() //
return
}
} }
//
const findClosestPoint = (x, y) => {
let minDistance = Infinity
let closestIndex = null
let list = allHistoryList.value[currentIndex.value]
list.forEach((point, index) => {
const distance = Math.sqrt((point.locationX - x) ** 2 + (point.locationY - y) ** 2)
if (distance < minDistance && distance < point.locationWide) {
// 10
minDistance = distance
closestIndex = index
}
})
return closestIndex
}
// //
const clickDrawSelectionArea = () => { const clickDrawSelectionArea = () => {
let points = allHistoryList.value[currentIndex.value] let points = allHistoryList.value[currentIndex.value]
@ -1348,6 +1511,8 @@ const clickDrawSelectionArea = () => {
// let routeList = state.drawSelectionPointList.filter((item) => item.type === 1) // let routeList = state.drawSelectionPointList.filter((item) => item.type === 1)
let routeList = state.drawSelectionPointList let routeList = state.drawSelectionPointList
console.log(routeList)
let isHaveId = binLocation.every((item) => { let isHaveId = binLocation.every((item) => {
item.id item.id
}) })
@ -1484,11 +1649,16 @@ const startDrag = (item, index, type) => {
} }
// //
const handleDrag = (event) => { const handleDrag = (event) => {
const x = disposeEventPoints(event).x let x = disposeEventPoints(event).x
const y = disposeEventPoints(event).y let y = disposeEventPoints(event).y
if (state.currentDragTarget.index !== null) { if (state.currentDragTarget.index !== null) {
const curve = state.mapRouteList[state.currentDragTarget.index] const curve = state.mapRouteList[state.currentDragTarget.index]
//
x = Math.max(0, Math.min(x, imgBgObj.width))
y = Math.max(0, Math.min(y, imgBgObj.height))
if (state.currentDragTarget.type === 'start') { if (state.currentDragTarget.type === 'start') {
curve.beginControlX = x curve.beginControlX = x
curve.beginControlY = y curve.beginControlY = y
@ -1499,27 +1669,16 @@ const handleDrag = (event) => {
} }
} }
// //
const endDrag = () => { const endDrag = (event) => {
let actualBeginControl = disposeEventPoint( const curve = state.mapRouteList[state.currentDragTarget.index]
state.mapRouteList[state.currentDragTarget.index].beginControlX, let actualBeginControl = disposeEventPoint(curve.beginControlX, curve.beginControlY)
state.mapRouteList[state.currentDragTarget.index].beginControlY let actualEndControl = disposeEventPoint(curve.endControlX, curve.endControlY)
)
let actualEndControl = disposeEventPoint(
state.mapRouteList[state.currentDragTarget.index].endControlX,
state.mapRouteList[state.currentDragTarget.index].endControlY
)
state.mapRouteList[state.currentDragTarget.index].actualBeginControlX = curve.actualBeginControlX = actualBeginControl.actualLocationX
actualBeginControl.actualLocationX curve.actualBeginControlY = actualBeginControl.actualLocationY
state.mapRouteList[state.currentDragTarget.index].actualBeginControlY =
actualBeginControl.actualLocationY
state.mapRouteList[state.currentDragTarget.index].actualEndControlX = curve.actualEndControlX = actualEndControl.actualLocationX
actualEndControl.actualLocationX curve.actualEndControlY = actualEndControl.actualLocationY
state.mapRouteList[state.currentDragTarget.index].actualEndControlY =
actualEndControl.actualLocationY
console.log(state.mapRouteList[state.currentDragTarget.index])
state.currentDragTarget = { index: null, type: null } state.currentDragTarget = { index: null, type: null }
window.removeEventListener('mousemove', handleDrag) window.removeEventListener('mousemove', handleDrag)
@ -1545,7 +1704,6 @@ const handleEditRoute = (item, index) => {
} }
// //
const handleChooseRoute = (item, index) => { const handleChooseRoute = (item, index) => {
console.log(item)
state.mapRouteList.forEach((curve, i) => { state.mapRouteList.forEach((curve, i) => {
curve.isSelected = i === index curve.isSelected = i === index
}) })
@ -1646,7 +1804,6 @@ const measureDistancesClick = (event) => {
} }
} }
} }
// //
const imgBgObj = reactive({ const imgBgObj = reactive({
imgUrl: '', imgUrl: '',
@ -1699,6 +1856,8 @@ const getAllNodeList = async () => {
positionMapId: imgBgObj.positionMapId positionMapId: imgBgObj.positionMapId
}) })
allMapPointInfo.value = [] allMapPointInfo.value = []
allHistoryList.value = []
currentIndex.value = 0
list.forEach((item) => { list.forEach((item) => {
item.layerSelectionShow = true // item.layerSelectionShow = true //
item.locationX = Number(item.locationX) item.locationX = Number(item.locationX)
@ -1771,7 +1930,6 @@ const getAllNodeList = async () => {
const getAllMapRoute = async () => { const getAllMapRoute = async () => {
state.mapRouteList = await MapApi.getPositionMapLineByPositionMapId(imgBgObj.positionMapId) state.mapRouteList = await MapApi.getPositionMapLineByPositionMapId(imgBgObj.positionMapId)
} }
// //
const saveMap = async () => { const saveMap = async () => {
const loading = ElLoading.service({ const loading = ElLoading.service({
@ -1816,7 +1974,6 @@ const saveNodeList = async () => {
const saveMapRoute = async () => { const saveMapRoute = async () => {
await MapApi.createOrEditOrDelPositionMapLine(imgBgObj.positionMapId, state.mapRouteList) await MapApi.createOrEditOrDelPositionMapLine(imgBgObj.positionMapId, state.mapRouteList)
} }
// //
const layerSelectionSuccess = (typeList) => { const layerSelectionSuccess = (typeList) => {
allHistoryList.value[currentIndex.value].forEach((item) => { allHistoryList.value[currentIndex.value].forEach((item) => {
@ -1828,13 +1985,13 @@ const layerSelectionSuccess = (typeList) => {
} }
}) })
} }
// //
const disposeEventPoints = (event) => { const disposeEventPoints = (event) => {
const rect = mapBackgroundRef.value.getBoundingClientRect() const rect = mapBackgroundRef.value.getBoundingClientRect()
const scrollLeft = mapBackgroundRef.value.scrollLeft // const scrollLeft = mapBackgroundRef.value.scrollLeft //
const scrollTop = mapBackgroundRef.value.scrollTop // const scrollTop = mapBackgroundRef.value.scrollTop //
const devicePixelRatio = window.devicePixelRatio || 1 // const devicePixelRatio = window.devicePixelRatio || 1 //
const devicePixelRatio = 1
// //
const x = (event.clientX - rect.left + scrollLeft) / state.imageChangeMultiple / devicePixelRatio const x = (event.clientX - rect.left + scrollLeft) / state.imageChangeMultiple / devicePixelRatio
@ -1862,7 +2019,6 @@ const disposeEventPoint = (x, y) => {
actualLocationY actualLocationY
} }
} }
document.onmousedown = function (e) { document.onmousedown = function (e) {
// //
if (e.button == 2) { if (e.button == 2) {
@ -1874,7 +2030,6 @@ document.onmousedown = function (e) {
currentItemIndex.value = -1 currentItemIndex.value = -1
} }
} }
// //
window.document.oncontextmenu = function () { window.document.oncontextmenu = function () {
return false return false
@ -1886,11 +2041,14 @@ onMounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.edit-map-page {
margin-bottom: 20px;
}
.map-container { .map-container {
position: relative; position: relative;
width: 100%; width: 100%;
overflow: auto; overflow: auto;
// height: 85vh;
.map-bg { .map-bg {
background-size: contain; background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -1905,6 +2063,7 @@ onMounted(() => {
.top-tool { .top-tool {
margin-top: 5px; margin-top: 5px;
margin-bottom: 3px;
.top-tool-list { .top-tool-list {
display: flex; display: flex;
align-items: center; align-items: center;
@ -1912,6 +2071,7 @@ onMounted(() => {
background-color: #fff; background-color: #fff;
padding: 0 12px; padding: 0 12px;
height: 70px; height: 70px;
box-shadow: rgba(0, 0, 0, 0.06) 0px 2px 3px;
.top-tool-item { .top-tool-item {
display: flex; display: flex;
@ -1952,7 +2112,7 @@ onMounted(() => {
.right-tool-list { .right-tool-list {
position: absolute; position: absolute;
right: 0; right: 0;
top: 94px; top: 114px;
background-color: #fff; background-color: #fff;
z-index: 999; z-index: 999;
text-align: center; text-align: center;
@ -1989,11 +2149,28 @@ onMounted(() => {
} }
.grid-show { .grid-show {
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px), // background: linear-gradient(-90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px),
linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px); // linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px);
background-size: // background-size:
10px 10px, // 20px 20px,
10px 10px; // 20px 20px;
width: 100%;
height: 100%;
background-image: repeating-linear-gradient(
to right,
rgba(0, 0, 0, 0.1),
rgba(0, 0, 0, 0.1) 1px,
transparent 1px,
transparent 50px
),
repeating-linear-gradient(
to bottom,
rgba(0, 0, 0, 0.1),
rgba(0, 0, 0, 0.1) 1px,
transparent 1px,
transparent 50px
);
} }
.svg-div { .svg-div {

View File

@ -1,110 +1,190 @@
<template> <template>
<div> <div>
<svg width="800" height="600"> <svg
<path ref="svgElement"
v-for="(curve, index) in curves" :width="width"
:height="height"
@mousedown="startDrawing"
@mousemove="drawLine"
@mouseup="stopDrawing"
@mouseleave="stopDrawing"
>
<!-- 渲染所有点 -->
<circle
v-for="(point, index) in points"
:key="index" :key="index"
:d="getCurvePath(curve)" :cx="point.x"
:stroke="curve.isSelected ? 'red' : 'blue'" :cy="point.y"
r="5"
fill="red"
@mousedown="startFromPoint(index, $event)"
/>
<!-- 渲染所有直线 -->
<path
v-for="(line, index) in lines"
:key="'line-' + index"
:d="`M ${line.startPointX} ${line.startPointY} L ${line.endPointX} ${line.endPointY}`"
stroke="black"
stroke-width="2" stroke-width="2"
fill="none" fill="none"
@mousedown="selectCurve(index)"
/> />
<circle
v-for="(curve, index) in curves" <!-- 实时绘制当前直线 -->
:key="'start-' + index" <path
:cx="curve.beginControlX" v-if="isDrawing"
:cy="curve.beginControlY" :d="`M ${startX} ${startY} L ${currentX} ${currentY}`"
r="5" stroke="blue"
fill="green" stroke-width="2"
@mousedown="startDrag(index, 'start')" fill="none"
/>
<circle
v-for="(curve, index) in curves"
:key="'end-' + index"
:cx="curve.endControlX"
:cy="curve.endControlY"
r="5"
fill="green"
@mousedown="startDrag(index, 'end')"
/> />
</svg> </svg>
<!-- 显示直线数据 -->
<div>
<h3>直线数据</h3>
<pre>{{ lines }}</pre>
</div>
</div> </div>
</template> </template>
<script setup> <script>
import { ref } from 'vue' import { ref } from 'vue'
// export default {
const curves = ref([ setup() {
{ const svgElement = ref(null) // SVG
startPointX: 100, const width = 800 // SVG
startPointY: 100, const height = 600 // SVG
endPointX: 300,
endPointY: 100, //
beginControlX: 100, const points = ref([
beginControlY: 100, { x: 10, y: 10 },
endControlX: 300, { x: 30, y: 100 },
endControlY: 100, { x: 40, y: 40 },
isSelected: false { x: 230, y: 400 },
}, { x: 750, y: 640 }
{ ])
startPointX: 200,
startPointY: 200, // 线
endPointX: 400, const lines = ref([])
endPointY: 200,
beginControlX: 200, // 线
beginControlY: 200, const isDrawing = ref(false)
endControlX: 400, const startX = ref(0)
endControlY: 200, const startY = ref(0)
isSelected: false const currentX = ref(0)
const currentY = ref(0)
const startPointIndex = ref(null) //
//
const startFromPoint = (index, event) => {
const point = points.value[index]
startX.value = point.x
startY.value = point.y
startPointIndex.value = index
isDrawing.value = true
event.preventDefault() //
} }
])
// 线 //
const dragging = ref({ const drawLine = (event) => {
index: null, if (isDrawing.value) {
type: null const rect = svgElement.value.getBoundingClientRect()
}) currentX.value = event.clientX - rect.left
currentY.value = event.clientY - rect.top
}
}
// 线 //
const getCurvePath = (curve) => { const stopDrawing = () => {
return `M${curve.startPointX},${curve.startPointY} C${curve.beginControlX},${curve.beginControlY} ${curve.endControlX},${curve.endControlY} ${curve.endPointX},${curve.endPointY}` if (isDrawing.value) {
} //
const endPointIndex = findClosestPoint(currentX.value, currentY.value)
// 线 if (endPointIndex !== null && endPointIndex !== startPointIndex.value) {
const selectCurve = (index) => { const endPoint = points.value[endPointIndex]
curves.value.forEach((curve, i) => { const newLine = {
curve.isSelected = i === index startPointX: startX.value,
startPointY: startY.value,
endPointX: endPoint.x,
endPointY: endPoint.y
}
// 线
const isDuplicate = lines.value.some(
(line) =>
(line.startPointX === newLine.startPointX &&
line.startPointY === newLine.startPointY &&
line.endPointX === newLine.endPointX &&
line.endPointY === newLine.endPointY) ||
(line.startPointX === newLine.endPointX &&
line.startPointY === newLine.endPointY &&
line.endPointX === newLine.startPointX &&
line.endPointY === newLine.startPointY)
)
if (!isDuplicate) {
// 线
lines.value.push(newLine)
}
}
//
isDrawing.value = false
startX.value = 0
startY.value = 0
currentX.value = 0
currentY.value = 0
startPointIndex.value = null
}
}
//
const findClosestPoint = (x, y) => {
let minDistance = Infinity
let closestIndex = null
points.value.forEach((point, index) => {
const distance = Math.sqrt((point.x - x) ** 2 + (point.y - y) ** 2)
if (distance < minDistance && distance < 10) {
// 10
minDistance = distance
closestIndex = index
}
}) })
console.log('Selected curve:', curves.value[index])
}
// return closestIndex
const startDrag = (index, type) => { }
dragging.value = { index, type }
window.addEventListener('mousemove', handleDrag)
window.addEventListener('mouseup', endDrag)
}
// return {
const handleDrag = (event) => { svgElement,
if (dragging.value.index !== null) { width,
const curve = curves.value[dragging.value.index] height,
if (dragging.value.type === 'start') { points,
curve.beginControlX = event.offsetX lines,
curve.beginControlY = event.offsetY isDrawing,
} else { startX,
curve.endControlX = event.offsetX startY,
curve.endControlY = event.offsetY currentX,
currentY,
startFromPoint,
drawLine,
stopDrawing
} }
} }
} }
//
const endDrag = () => {
dragging.value = { index: null, type: null }
window.removeEventListener('mousemove', handleDrag)
window.removeEventListener('mouseup', endDrag)
}
</script> </script>
<style scoped>
svg {
border: 1px solid #ccc;
background-color: #f9f9f9;
}
pre {
background-color: #f5f5f5;
padding: 10px;
border-radius: 5px;
}
</style>