feat(editor): dock flow arrows square at any pipe angle
Swap the filled-triangle arrowhead for an open arrow on flow pipes and information links, and route flow pipes through a custom cubic edge whose horizontal flatten arm scales with the vertical drop, not just the horizontal gap. Vue Flow's default arm collapses toward zero when the valve sits nearly above the stock, so a steep pipe stayed flat only in its last pixels and the arrowhead detached from the visible line. The pipe now keeps a real horizontal run into the stock's left edge at any approach angle.
This commit is contained in:
@@ -36,6 +36,7 @@ import GlossPanel from "./GlossPanel.vue"
|
||||
import LoopOverlay from "./LoopOverlay.vue"
|
||||
import Palette from "./Palette.vue"
|
||||
import InfoLinkEdge from "./edges/InfoLinkEdge.vue"
|
||||
import PipeEdge from "./edges/PipeEdge.vue"
|
||||
import CloudNode from "./nodes/CloudNode.vue"
|
||||
import ConverterNode from "./nodes/ConverterNode.vue"
|
||||
import FlowNode from "./nodes/FlowNode.vue"
|
||||
@@ -405,6 +406,9 @@ onBeforeUnmount(() => {
|
||||
<CloudNode v-bind="nodeProps" />
|
||||
</template>
|
||||
|
||||
<template #edge-pipe="edgeProps">
|
||||
<PipeEdge v-bind="edgeProps" />
|
||||
</template>
|
||||
<template #edge-info="edgeProps">
|
||||
<InfoLinkEdge v-bind="edgeProps" />
|
||||
</template>
|
||||
|
||||
35
src/components/edges/PipeEdge.vue
Normal file
35
src/components/edges/PipeEdge.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Flow pipe edge (C3) — the source→valve and valve→target segments of a Flow.
|
||||
*
|
||||
* The pipe leaves the source on the right and docks square into the target's
|
||||
* left edge (horizontal tangents both ends), so the arrowhead always enters the
|
||||
* stock straight-on. Vue Flow's default bezier does the same — but it sizes the
|
||||
* horizontal "flatten" arm from the *horizontal* gap alone, so when the valve
|
||||
* sits nearly above the stock that arm collapses to ~zero: the curve stays steep
|
||||
* and snaps flat only in its final pixels, leaving the arrowhead on a stub of
|
||||
* horizontal line while the visible stroke arrives steep — the head detaches.
|
||||
*
|
||||
* Sizing the arm from the vertical drop too keeps a real horizontal run before
|
||||
* the stock at any approach angle, so the arrowhead sits on the line and still
|
||||
* docks square. BaseEdge draws the stroke (same .vue-flow__edge-path class, so
|
||||
* theme stroke/width are unchanged) and carries the markerEnd through.
|
||||
*/
|
||||
import { BaseEdge, type EdgeProps } from "@vue-flow/core"
|
||||
import { computed } from "vue"
|
||||
import type { EdgeData } from "@/model/projection"
|
||||
|
||||
const props = defineProps<EdgeProps<EdgeData>>()
|
||||
|
||||
const path = computed(() => {
|
||||
const { sourceX: sx, sourceY: sy, targetX: tx, targetY: ty } = props
|
||||
const arm = Math.min(120, Math.max(30, Math.abs(tx - sx) * 0.5, Math.abs(ty - sy) * 0.45))
|
||||
// Cubic with horizontal control points: out the source's right, into the
|
||||
// target's left. `arm` is the run over which each end stays horizontal.
|
||||
return `M ${sx},${sy} C ${sx + arm},${sy} ${tx - arm},${ty} ${tx},${ty}`
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BaseEdge :id="props.id" :path="path" :marker-end="props.markerEnd" :style="props.style" />
|
||||
</template>
|
||||
@@ -54,6 +54,7 @@ export function projectEdges(model: Model): FlowGraphEdge[] {
|
||||
// Pipe in: source → valve. No arrowhead — the valve is the visual midpoint.
|
||||
edges.push({
|
||||
id: `${node.id}::in`,
|
||||
type: "pipe",
|
||||
source: node.source,
|
||||
sourceHandle: HANDLE_OUT,
|
||||
target: node.id,
|
||||
@@ -64,13 +65,14 @@ export function projectEdges(model: Model): FlowGraphEdge[] {
|
||||
// Pipe out: valve → target. Arrowhead carries the flow direction.
|
||||
edges.push({
|
||||
id: `${node.id}::out`,
|
||||
type: "pipe",
|
||||
source: node.id,
|
||||
sourceHandle: HANDLE_OUT,
|
||||
target: node.target,
|
||||
targetHandle: HANDLE_IN,
|
||||
data: { kind: "pipe" },
|
||||
style: { strokeWidth: "2.5px" },
|
||||
markerEnd: "arrowclosed",
|
||||
markerEnd: "arrow",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ export function projectEdges(model: Model): FlowGraphEdge[] {
|
||||
targetHandle: HANDLE_IN,
|
||||
data: { kind: "info", polarity: link.polarity },
|
||||
style: { strokeDasharray: "5 4" },
|
||||
markerEnd: "arrowclosed",
|
||||
markerEnd: "arrow",
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user