feat: Pin移动连线也跟着移动
This commit is contained in:
149
src/components/equipments/Wire.vue
Normal file
149
src/components/equipments/Wire.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<g :data-wire-id="props.id">
|
||||
<path
|
||||
:d="pathData"
|
||||
fill="none"
|
||||
:stroke="computedStroke"
|
||||
:stroke-width="strokeWidth"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
:class="{ 'wire-active': props.isActive }"
|
||||
@click="handleClick"
|
||||
/>
|
||||
<!-- 可选:添加连线标签或状态指示器 -->
|
||||
<text
|
||||
v-if="showLabel"
|
||||
:x="labelPosition.x"
|
||||
:y="labelPosition.y"
|
||||
class="wire-label"
|
||||
>{{ props.constraint || '' }}</text>
|
||||
</g>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, defineEmits, reactive } from 'vue';
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
startX: number;
|
||||
startY: number;
|
||||
endX: number;
|
||||
endY: number;
|
||||
strokeColor?: string;
|
||||
strokeWidth?: number;
|
||||
isActive?: boolean;
|
||||
routingMode?: 'auto' | 'orthogonal' | 'direct';
|
||||
// 针脚引用属性
|
||||
startComponentId?: string;
|
||||
startPinLabel?: string;
|
||||
endComponentId?: string;
|
||||
endPinLabel?: string;
|
||||
// 添加约束属性
|
||||
constraint?: string;
|
||||
// 显示标签
|
||||
showLabel?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
strokeColor: '#4a5568',
|
||||
strokeWidth: 2,
|
||||
isActive: false,
|
||||
routingMode: 'orthogonal',
|
||||
showLabel: false,
|
||||
constraint: ''
|
||||
});
|
||||
|
||||
const computedStroke = computed(() => props.isActive ? '#ff9800' : props.strokeColor);
|
||||
|
||||
const emit = defineEmits(['click', 'update:active', 'update:position']);
|
||||
|
||||
function handleClick(event: MouseEvent) {
|
||||
emit('click', { id: props.id, event });
|
||||
}
|
||||
|
||||
// 计算标签位置 - 放在连线中间
|
||||
const labelPosition = computed(() => {
|
||||
return {
|
||||
x: (props.startX + props.endX) / 2,
|
||||
y: (props.startY + props.endY) / 2 - 5
|
||||
};
|
||||
});
|
||||
|
||||
const pathData = computed(() => {
|
||||
return calculateOrthogonalPath(props.startX, props.startY, props.endX, props.endY);
|
||||
});
|
||||
|
||||
function calculateOrthogonalPath(startX: number, startY: number, endX: number, endY: number) {
|
||||
// 计算两点之间的水平和垂直距离
|
||||
const dx = endX - startX;
|
||||
const dy = endY - startY;
|
||||
|
||||
// 如果在同一水平或垂直线上,直接连线
|
||||
if (dx === 0 || dy === 0) {
|
||||
return `M ${startX} ${startY} L ${endX} ${endY}`;
|
||||
}
|
||||
|
||||
const absDx = Math.abs(dx);
|
||||
const absDy = Math.abs(dy);
|
||||
if (absDx > absDy) {
|
||||
// 先水平移动,然后垂直移动
|
||||
const middleX = startX + dx * 0.5;
|
||||
return `M ${startX} ${startY} L ${middleX} ${startY} L ${middleX} ${endY} L ${endX} ${endY}`;
|
||||
} else {
|
||||
// 先垂直移动,然后水平移动
|
||||
const middleY = startY + dy * 0.5;
|
||||
return `M ${startX} ${startY} L ${startX} ${middleY} L ${endX} ${middleY} L ${endX} ${endY}`;
|
||||
}
|
||||
}
|
||||
// 暴露方法,用于获取这条连线的信息
|
||||
defineExpose({ id: props.id,
|
||||
getInfo: () => ({
|
||||
id: props.id,
|
||||
startComponentId: props.startComponentId,
|
||||
startPinLabel: props.startPinLabel,
|
||||
endComponentId: props.endComponentId,
|
||||
endPinLabel: props.endPinLabel,
|
||||
constraint: props.constraint
|
||||
}),
|
||||
// 更新连线位置
|
||||
updatePosition: (newStartX: number, newStartY: number, newEndX: number, newEndY: number) => {
|
||||
// 由于 props 是只读的,我们只能通过事件通知父组件更新
|
||||
emit('update:position', {
|
||||
id: props.id,
|
||||
startX: newStartX,
|
||||
startY: newStartY,
|
||||
endX: newEndX,
|
||||
endY: newEndY
|
||||
});
|
||||
},
|
||||
// 获取连线的针脚情况
|
||||
getPinPosition: () => null, // 为了与其他组件接口一致,但Wire不是针脚组件
|
||||
// 获取连线的路由模式
|
||||
getRoutingMode: () => props.routingMode,
|
||||
// 设置连线状态(如高亮等)
|
||||
setActive: (active: boolean) => {
|
||||
emit('update:active', active);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wire-active {
|
||||
stroke-dasharray: 5;
|
||||
animation: dash 0.5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes dash {
|
||||
to {
|
||||
stroke-dashoffset: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.wire-label {
|
||||
font-size: 10px;
|
||||
fill: #666;
|
||||
text-anchor: middle;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user