128 lines
2.9 KiB
Vue
128 lines
2.9 KiB
Vue
<template>
|
|
<div class="box">
|
|
<svg :width="boxWidth" :height="boxHeight">
|
|
<path
|
|
v-for="(curve, index) in curves"
|
|
:key="index"
|
|
:d="getCurvePath(curve)"
|
|
:stroke="curve.isSelected ? 'red' : 'blue'"
|
|
stroke-width="2"
|
|
fill="none"
|
|
@mousedown="selectCurve(index)"
|
|
/>
|
|
<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>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
|
|
// 盒子的宽度和高度
|
|
const boxWidth = ref(800)
|
|
const boxHeight = ref(600)
|
|
|
|
// 初始点位数据
|
|
const curves = ref([
|
|
{
|
|
startX: 100,
|
|
startY: 100,
|
|
endX: 300,
|
|
endY: 100,
|
|
startControlX: 100,
|
|
startControlY: 100,
|
|
endControlX: 300,
|
|
endControlY: 100,
|
|
isSelected: false
|
|
},
|
|
{
|
|
startX: 200,
|
|
startY: 200,
|
|
endX: 400,
|
|
endY: 200,
|
|
startControlX: 200,
|
|
startControlY: 200,
|
|
endControlX: 400,
|
|
endControlY: 400,
|
|
isSelected: false
|
|
}
|
|
])
|
|
|
|
// 当前拖动的曲线索引和控制点类型
|
|
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>
|
|
|
|
<style scoped>
|
|
.box {
|
|
border: 1px solid black;
|
|
}
|
|
</style>
|