地图编辑
This commit is contained in:
parent
6db5611af3
commit
d74f617af9
@ -1,6 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 新增设备 -->
|
<!-- 新增设备 -->
|
||||||
<Dialog v-model="dialogFormVisible" title="编辑路线" width="780" class="map-edit-route-dialog">
|
<Dialog
|
||||||
|
v-model="dialogFormVisible"
|
||||||
|
title="编辑路线"
|
||||||
|
width="780"
|
||||||
|
class="map-edit-route-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
|
>
|
||||||
<el-form :model="form" label-width="120" ref="ruleFormRef">
|
<el-form :model="form" label-width="120" ref="ruleFormRef">
|
||||||
<el-row :gutter="30">
|
<el-row :gutter="30">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@ -215,7 +221,11 @@ const open = (item) => {
|
|||||||
form.value = item
|
form.value = item
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['editMapRouteDialogSubmit'])
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['editMapRouteDialogSubmit', 'addEventListener'])
|
||||||
const submitForm = async (formEl) => {
|
const submitForm = async (formEl) => {
|
||||||
if (!formEl) return
|
if (!formEl) return
|
||||||
await formEl.validate(async (valid, fields) => {
|
await formEl.validate(async (valid, fields) => {
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model="dialogFormVisible" title="节点属性" width="540" class="node-form-dialog">
|
<Dialog
|
||||||
|
v-model="dialogFormVisible"
|
||||||
|
title="节点属性"
|
||||||
|
width="540"
|
||||||
|
class="node-form-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
|
>
|
||||||
<el-form :model="form" label-width="auto" ref="ruleFormRef">
|
<el-form :model="form" label-width="auto" ref="ruleFormRef">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
label="X"
|
label="X"
|
||||||
@ -169,7 +175,7 @@ const rules = reactive({
|
|||||||
layersNumber: [{ required: true, message: '请输入层数', trigger: 'blur' }]
|
layersNumber: [{ required: true, message: '请输入层数', trigger: 'blur' }]
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['submitNodeSuccess'])
|
const emit = defineEmits(['submitNodeSuccess', 'addEventListener'])
|
||||||
const submit = async (formEl) => {
|
const submit = async (formEl) => {
|
||||||
if (!formEl) return
|
if (!formEl) return
|
||||||
await formEl.validate((valid, fields) => {
|
await formEl.validate((valid, fields) => {
|
||||||
@ -236,6 +242,10 @@ const submit = async (formEl) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
const equipmentList = ref([]) //用过的设备列表
|
const equipmentList = ref([]) //用过的设备列表
|
||||||
const open = (item, list) => {
|
const open = (item, list) => {
|
||||||
form.value = item
|
form.value = item
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model="dialogFormVisible" title="设备" width="586" class="equipment-form-dialog">
|
<Dialog
|
||||||
|
v-model="dialogFormVisible"
|
||||||
|
title="设备"
|
||||||
|
width="586"
|
||||||
|
class="equipment-form-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
|
>
|
||||||
<div class="device-list">
|
<div class="device-list">
|
||||||
<div class="device-item" v-for="(item, index) in deviceList" :key="index">
|
<div class="device-item" v-for="(item, index) in deviceList" :key="index">
|
||||||
<img class="img" :src="item.url" />
|
<img class="img" :src="item.url" />
|
||||||
@ -145,6 +151,11 @@ const open = (list) => {
|
|||||||
getDeviceList()
|
getDeviceList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['addEventListener'])
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
const initAddForm = () => {
|
const initAddForm = () => {
|
||||||
deviceInfo.value.deviceInfoId = ''
|
deviceInfo.value.deviceInfoId = ''
|
||||||
deviceInfo.value.deviceType = ''
|
deviceInfo.value.deviceType = ''
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
title="区域管理"
|
title="区域管理"
|
||||||
width="600"
|
width="600"
|
||||||
class="item-area-management-dialog"
|
class="item-area-management-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
>
|
>
|
||||||
<el-table
|
<el-table
|
||||||
:data="list"
|
:data="list"
|
||||||
@ -55,6 +56,11 @@ const open = () => {
|
|||||||
getWareHouseList()
|
getWareHouseList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['addEventListener'])
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中
|
const loading = ref(true) // 列表的加载中
|
||||||
const total = ref(0) // 列表的总页数
|
const total = ref(0) // 列表的总页数
|
||||||
const list = ref()
|
const list = ref()
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
title="物料区域设置"
|
title="物料区域设置"
|
||||||
width="600"
|
width="600"
|
||||||
class="equipment-form-dialog"
|
class="equipment-form-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
>
|
>
|
||||||
<el-form :model="form" label-width="110" ref="ruleFormRef">
|
<el-form :model="form" label-width="110" ref="ruleFormRef">
|
||||||
<el-form-item label="物料区域名称" prop="skuInfo" required>
|
<el-form-item label="物料区域名称" prop="skuInfo" required>
|
||||||
@ -64,6 +65,11 @@ const open = (list) => {
|
|||||||
form.value.skuInfo = ''
|
form.value.skuInfo = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['addEventListener'])
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
const submitForm = async (formEl) => {
|
const submitForm = async (formEl) => {
|
||||||
if (!formEl) return
|
if (!formEl) return
|
||||||
await formEl.validate(async (valid, fields) => {
|
await formEl.validate(async (valid, fields) => {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
title="线库管理"
|
title="线库管理"
|
||||||
width="600"
|
width="600"
|
||||||
class="line-library-management-dialog"
|
class="line-library-management-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
>
|
>
|
||||||
<el-table
|
<el-table
|
||||||
:data="list"
|
:data="list"
|
||||||
@ -54,6 +55,11 @@ const open = () => {
|
|||||||
getLineLibraryList()
|
getLineLibraryList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['addEventListener'])
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中
|
const loading = ref(true) // 列表的加载中
|
||||||
const total = ref(0) // 列表的总页数
|
const total = ref(0) // 列表的总页数
|
||||||
const list = ref()
|
const list = ref()
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 新增设备 -->
|
<!-- 新增设备 -->
|
||||||
<Dialog v-model="dialogFormVisible" title="线库设置" width="600" class="equipment-form-dialog">
|
<Dialog
|
||||||
|
v-model="dialogFormVisible"
|
||||||
|
title="线库设置"
|
||||||
|
width="600"
|
||||||
|
class="equipment-form-dialog"
|
||||||
|
@close="dialogClose"
|
||||||
|
>
|
||||||
<el-form :model="form" label-width="110" ref="lineFormRef" :rules="rules">
|
<el-form :model="form" label-width="110" ref="lineFormRef" :rules="rules">
|
||||||
<el-form-item label="线库名称" prop="laneName" required>
|
<el-form-item label="线库名称" prop="laneName" required>
|
||||||
<el-input v-model="form.laneName" placeholder="请输入线库名称" />
|
<el-input v-model="form.laneName" placeholder="请输入线库名称" />
|
||||||
@ -53,6 +59,11 @@ const open = (list) => {
|
|||||||
form.value.laneName = ''
|
form.value.laneName = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['addEventListener'])
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
const submitLineLibraryForm = async () => {
|
const submitLineLibraryForm = async () => {
|
||||||
await lineFormRef.value.validate(async (valid, fields) => {
|
await lineFormRef.value.validate(async (valid, fields) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
@ -527,6 +527,7 @@
|
|||||||
ref="editNodePropertiesRef"
|
ref="editNodePropertiesRef"
|
||||||
:positionMapId="imgBgObj.positionMapId"
|
:positionMapId="imgBgObj.positionMapId"
|
||||||
@submitNodeSuccess="submitNodeSuccess"
|
@submitNodeSuccess="submitNodeSuccess"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
/>
|
/>
|
||||||
<!-- 文字输入弹窗 -->
|
<!-- 文字输入弹窗 -->
|
||||||
<textFormToolDialog
|
<textFormToolDialog
|
||||||
@ -542,29 +543,41 @@
|
|||||||
@layerSelectionSuccess="layerSelectionSuccess"
|
@layerSelectionSuccess="layerSelectionSuccess"
|
||||||
/>
|
/>
|
||||||
<!-- 设备弹窗选择 -->
|
<!-- 设备弹窗选择 -->
|
||||||
<equipmentToolDialog ref="equipmentToolDialogRef" :positionMapId="imgBgObj.positionMapId" />
|
<equipmentToolDialog
|
||||||
|
ref="equipmentToolDialogRef"
|
||||||
|
:positionMapId="imgBgObj.positionMapId"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
|
/>
|
||||||
<!-- 区域选择 -->
|
<!-- 区域选择 -->
|
||||||
<itemAreaSettingDialog ref="itemAreaSettingDialogRef" :positionMapId="imgBgObj.positionMapId" />
|
<itemAreaSettingDialog
|
||||||
|
ref="itemAreaSettingDialogRef"
|
||||||
|
:positionMapId="imgBgObj.positionMapId"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
|
/>
|
||||||
<!-- 线库设置 -->
|
<!-- 线库设置 -->
|
||||||
<lineLibrarySettingDialog
|
<lineLibrarySettingDialog
|
||||||
ref="lineLibrarySettingDialogRef"
|
ref="lineLibrarySettingDialogRef"
|
||||||
:positionMapId="imgBgObj.positionMapId"
|
:positionMapId="imgBgObj.positionMapId"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
/>
|
/>
|
||||||
<!-- 编辑地图路线 -->
|
<!-- 编辑地图路线 -->
|
||||||
<editMapRouteDialog
|
<editMapRouteDialog
|
||||||
ref="editMapRouteDialogRef"
|
ref="editMapRouteDialogRef"
|
||||||
@editMapRouteDialogSubmit="editMapRouteDialogSubmit"
|
@editMapRouteDialogSubmit="editMapRouteDialogSubmit"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
:imgBgObj="imgBgObj"
|
:imgBgObj="imgBgObj"
|
||||||
/>
|
/>
|
||||||
<!-- 线库管理 -->
|
<!-- 线库管理 -->
|
||||||
<lineLibraryManagementDialog
|
<lineLibraryManagementDialog
|
||||||
ref="lineLibraryManagementDialogRef"
|
ref="lineLibraryManagementDialogRef"
|
||||||
:positionMapId="imgBgObj.positionMapId"
|
:positionMapId="imgBgObj.positionMapId"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
/>
|
/>
|
||||||
<!-- 区域管理 -->
|
<!-- 区域管理 -->
|
||||||
<itemAreaManagementDialog
|
<itemAreaManagementDialog
|
||||||
ref="itemAreaManagementDialogRef"
|
ref="itemAreaManagementDialogRef"
|
||||||
:positionMapId="imgBgObj.positionMapId"
|
:positionMapId="imgBgObj.positionMapId"
|
||||||
|
@addEventListener="addEventListener"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -693,6 +706,7 @@ const activatedHandle = (item, index) => {
|
|||||||
//节点编辑
|
//节点编辑
|
||||||
if (toolbarSwitchType.value === 'editNode' && item.type !== 7) {
|
if (toolbarSwitchType.value === 'editNode' && item.type !== 7) {
|
||||||
let list = state.allMapPointInfo.filter((item) => item.type === 3)
|
let list = state.allMapPointInfo.filter((item) => item.type === 3)
|
||||||
|
removeEventListener() //移除监听
|
||||||
editNodePropertiesRef.value.open(JSON.parse(JSON.stringify(item)), list)
|
editNodePropertiesRef.value.open(JSON.parse(JSON.stringify(item)), list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1222,9 +1236,11 @@ const toolbarClick = async (item) => {
|
|||||||
break
|
break
|
||||||
case 'lineLibraryManage':
|
case 'lineLibraryManage':
|
||||||
// 线库管理
|
// 线库管理
|
||||||
|
removeEventListener() //移除监听
|
||||||
lineLibraryManagementDialogRef.value.open()
|
lineLibraryManagementDialogRef.value.open()
|
||||||
break
|
break
|
||||||
case 'regionManage':
|
case 'regionManage':
|
||||||
|
removeEventListener() //移除监听
|
||||||
itemAreaManagementDialogRef.value.open()
|
itemAreaManagementDialogRef.value.open()
|
||||||
// 区域管理
|
// 区域管理
|
||||||
break
|
break
|
||||||
@ -1307,6 +1323,7 @@ const toolbarClick = async (item) => {
|
|||||||
let equipmentList = state.allMapPointInfo.filter((item) => {
|
let equipmentList = state.allMapPointInfo.filter((item) => {
|
||||||
return item.type === 3
|
return item.type === 3
|
||||||
})
|
})
|
||||||
|
removeEventListener() //移除监听
|
||||||
equipmentToolDialogRef.value.open(equipmentList)
|
equipmentToolDialogRef.value.open(equipmentList)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1628,6 +1645,7 @@ const clickDrawSelectionArea = () => {
|
|||||||
message.warning('您选择的库位存在未保存的')
|
message.warning('您选择的库位存在未保存的')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
removeEventListener() //移除监听
|
||||||
lineLibrarySettingDialogRef.value.open(binLocation)
|
lineLibrarySettingDialogRef.value.open(binLocation)
|
||||||
}
|
}
|
||||||
//区域
|
//区域
|
||||||
@ -1643,6 +1661,7 @@ const clickDrawSelectionArea = () => {
|
|||||||
message.warning('您选择的库位存在未保存的')
|
message.warning('您选择的库位存在未保存的')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
removeEventListener() //移除监听
|
||||||
itemAreaSettingDialogRef.value.open(binLocation)
|
itemAreaSettingDialogRef.value.open(binLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1797,6 +1816,7 @@ const handleEditRoute = (item, index) => {
|
|||||||
})
|
})
|
||||||
state.currentDragTarget.index = index
|
state.currentDragTarget.index = index
|
||||||
state.selectedCurve = item
|
state.selectedCurve = item
|
||||||
|
removeEventListener() //移除监听
|
||||||
editMapRouteDialogRef.value.open(JSON.parse(JSON.stringify(item)))
|
editMapRouteDialogRef.value.open(JSON.parse(JSON.stringify(item)))
|
||||||
}
|
}
|
||||||
//单击 选中
|
//单击 选中
|
||||||
@ -1965,7 +1985,7 @@ const getAllNodeList = async () => {
|
|||||||
item.dataList = []
|
item.dataList = []
|
||||||
item.locationDeep = 50
|
item.locationDeep = 50
|
||||||
item.locationWide = 50
|
item.locationWide = 50
|
||||||
item.draggable = false
|
item.draggable = true
|
||||||
item.resizable = false
|
item.resizable = false
|
||||||
item.rotatable = false
|
item.rotatable = false
|
||||||
item.lockAspectRatio = true
|
item.lockAspectRatio = true
|
||||||
@ -2137,6 +2157,22 @@ const cmConversionPx = (cWidth, cHeight) => {
|
|||||||
pHeight
|
pHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//计算箭头坐标的值
|
||||||
|
const getSingleArrowStart = (item) => {
|
||||||
|
let distance =
|
||||||
|
Math.sqrt((item.endPointX - item.startPointX) ** 2 + (item.endPointY - item.startPointY) ** 2) /
|
||||||
|
2 +
|
||||||
|
10
|
||||||
|
|
||||||
|
return distance
|
||||||
|
}
|
||||||
|
const getDoubleArrowStart = (item) => {
|
||||||
|
let distance =
|
||||||
|
Math.sqrt((item.endPointX - item.startPointX) ** 2 + (item.endPointY - item.startPointY) ** 2) /
|
||||||
|
2 -
|
||||||
|
10
|
||||||
|
return distance
|
||||||
|
}
|
||||||
|
|
||||||
document.onmousedown = function (e) {
|
document.onmousedown = function (e) {
|
||||||
//左击
|
//左击
|
||||||
@ -2153,7 +2189,6 @@ document.onmousedown = function (e) {
|
|||||||
window.document.oncontextmenu = function () {
|
window.document.oncontextmenu = function () {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//监听键盘事件
|
//监听键盘事件
|
||||||
const handleKeyDown = (event) => {
|
const handleKeyDown = (event) => {
|
||||||
if (event.ctrlKey) {
|
if (event.ctrlKey) {
|
||||||
@ -2181,6 +2216,13 @@ const handleKeyDown = (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addEventListener = () => {
|
||||||
|
window.addEventListener('keydown', handleKeyDown)
|
||||||
|
}
|
||||||
|
const removeEventListener = () => {
|
||||||
|
window.removeEventListener('keydown', handleKeyDown)
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getMapList()
|
getMapList()
|
||||||
window.addEventListener('keydown', handleKeyDown)
|
window.addEventListener('keydown', handleKeyDown)
|
||||||
|
@ -1,32 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="box">
|
<div>
|
||||||
<svg :width="boxWidth" :height="boxHeight">
|
<!-- 控制箭头朝向的选择框 -->
|
||||||
|
<select v-model="arrowDirection">
|
||||||
|
<option value="right">向右</option>
|
||||||
|
<option value="left">向左</option>
|
||||||
|
<option value="up">向上</option>
|
||||||
|
<option value="down">向下</option>
|
||||||
|
</select>
|
||||||
|
<!-- 控制单向或双向箭头的选择框 -->
|
||||||
|
<select v-model="isDoubleArrow">
|
||||||
|
<option value="false">单向箭头</option>
|
||||||
|
<option value="true">双向箭头</option>
|
||||||
|
</select>
|
||||||
|
<!-- 控制箭头大小的输入框 -->
|
||||||
|
<input type="number" v-model="arrowSize" min="1" max="50" placeholder="箭头大小" />
|
||||||
|
<!-- SVG容器 -->
|
||||||
|
<svg width="200" height="200">
|
||||||
|
<!-- 定义箭头样式 -->
|
||||||
|
<defs>
|
||||||
|
<!-- 单向箭头 -->
|
||||||
|
<marker
|
||||||
|
id="single-arrow"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
refX="10"
|
||||||
|
refY="5"
|
||||||
|
markerWidth=":arrowSize"
|
||||||
|
markerHeight=":arrowSize"
|
||||||
|
orient="auto-start-reverse"
|
||||||
|
>
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="black" />
|
||||||
|
</marker>
|
||||||
|
<!-- 双向箭头 -->
|
||||||
|
<marker
|
||||||
|
id="double-arrow-start"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
refX="0"
|
||||||
|
refY="5"
|
||||||
|
markerWidth=":arrowSize"
|
||||||
|
markerHeight=":arrowSize"
|
||||||
|
orient="auto-start-reverse"
|
||||||
|
>
|
||||||
|
<path d="M 10 0 L 0 5 L 10 10 z" fill="black" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<!-- 根据变量绘制线条 -->
|
||||||
<path
|
<path
|
||||||
v-for="(curve, index) in curves"
|
:d="getPath()"
|
||||||
:key="index"
|
stroke="black"
|
||||||
:d="getCurvePath(curve)"
|
|
||||||
:stroke="curve.isSelected ? 'red' : 'blue'"
|
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
fill="none"
|
fill="none"
|
||||||
@mousedown="selectCurve(index)"
|
:marker-start="isDoubleArrow === 'true' ? 'url(#double-arrow-start)' : ''"
|
||||||
/>
|
:marker-end="isDoubleArrow === 'true' ? 'url(#single-arrow)' : 'url(#single-arrow)'"
|
||||||
<circle
|
|
||||||
v-for="(curve, index) in curves"
|
|
||||||
:key="'start-' + index"
|
|
||||||
:cx="curve.startControlX"
|
|
||||||
:cy="curve.startControlY"
|
|
||||||
r="5"
|
|
||||||
fill="green"
|
|
||||||
@mousedown="startDrag(index, 'start')"
|
|
||||||
/>
|
|
||||||
<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>
|
</div>
|
||||||
@ -35,93 +59,32 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
// 盒子的宽度和高度
|
// 定义响应式变量
|
||||||
const boxWidth = ref(800)
|
const arrowDirection = ref('right')
|
||||||
const boxHeight = ref(600)
|
const isDoubleArrow = ref('false')
|
||||||
|
const arrowSize = ref(10)
|
||||||
|
|
||||||
// 初始点位数据
|
// 根据箭头朝向生成路径
|
||||||
const curves = ref([
|
const getPath = () => {
|
||||||
{
|
let startX = 20
|
||||||
startX: 100,
|
let startY = 100
|
||||||
startY: 100,
|
let endX = 180
|
||||||
endX: 300,
|
let endY = 100
|
||||||
endY: 100,
|
|
||||||
startControlX: 100,
|
switch (arrowDirection.value) {
|
||||||
startControlY: 100,
|
case 'left':
|
||||||
endControlX: 300,
|
;[startX, endX] = [endX, startX]
|
||||||
endControlY: 100,
|
break
|
||||||
isSelected: false
|
case 'up':
|
||||||
},
|
startY = 180
|
||||||
{
|
endY = 20
|
||||||
startX: 200,
|
break
|
||||||
startY: 200,
|
case 'down':
|
||||||
endX: 400,
|
startY = 20
|
||||||
endY: 200,
|
endY = 180
|
||||||
startControlX: 200,
|
break
|
||||||
startControlY: 200,
|
|
||||||
endControlX: 400,
|
|
||||||
endControlY: 400,
|
|
||||||
isSelected: false
|
|
||||||
}
|
}
|
||||||
])
|
|
||||||
|
|
||||||
// 当前拖动的曲线索引和控制点类型
|
return `M ${startX} ${startY} L ${endX} ${endY}`
|
||||||
const dragging = ref({
|
|
||||||
index: null,
|
|
||||||
type: null
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取曲线的路径字符串
|
|
||||||
const getCurvePath = (curve) => {
|
|
||||||
return `M${curve.startX},${curve.startY} C${curve.startControlX},${curve.startControlY} ${curve.endControlX},${curve.endControlY} ${curve.endX},${curve.endY}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 选中曲线
|
|
||||||
const selectCurve = (index) => {
|
|
||||||
curves.value.forEach((curve, i) => {
|
|
||||||
curve.isSelected = i === index
|
|
||||||
})
|
|
||||||
console.log('Selected curve:', curves.value[index])
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始拖动控制点
|
|
||||||
const startDrag = (index, type) => {
|
|
||||||
dragging.value = { index, type }
|
|
||||||
window.addEventListener('mousemove', handleDrag)
|
|
||||||
window.addEventListener('mouseup', endDrag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理拖动事件
|
|
||||||
const handleDrag = (event) => {
|
|
||||||
if (dragging.value.index !== null) {
|
|
||||||
const curve = curves.value[dragging.value.index]
|
|
||||||
let newX = event.offsetX
|
|
||||||
let newY = event.offsetY
|
|
||||||
|
|
||||||
// 确保控制点不超出盒子范围
|
|
||||||
newX = Math.max(0, Math.min(newX, boxWidth.value))
|
|
||||||
newY = Math.max(0, Math.min(newY, boxHeight.value))
|
|
||||||
|
|
||||||
if (dragging.value.type === 'start') {
|
|
||||||
curve.startControlX = newX
|
|
||||||
curve.startControlY = newY
|
|
||||||
} else {
|
|
||||||
curve.endControlX = newX
|
|
||||||
curve.endControlY = newY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 结束拖动
|
|
||||||
const endDrag = () => {
|
|
||||||
dragging.value = { index: null, type: null }
|
|
||||||
window.removeEventListener('mousemove', handleDrag)
|
|
||||||
window.removeEventListener('mouseup', endDrag)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.box {
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
Loading…
Reference in New Issue
Block a user