From 7aa1773e0246d76335553f67dede8dac584f9c48 Mon Sep 17 00:00:00 2001 From: Braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Fri, 8 Apr 2022 10:34:28 +0200 Subject: [PATCH] feat(examples): Add floating edges example --- examples/router.ts | 4 + .../FloatingEdges/FloatingConnectionLine.vue | 38 +++++++ examples/src/FloatingEdges/FloatingEdge.vue | 47 ++++++++ examples/src/FloatingEdges/FloatingEdges.vue | 39 +++++++ .../src/FloatingEdges/floating-edge-utils.ts | 104 ++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 examples/src/FloatingEdges/FloatingConnectionLine.vue create mode 100644 examples/src/FloatingEdges/FloatingEdge.vue create mode 100644 examples/src/FloatingEdges/FloatingEdges.vue create mode 100644 examples/src/FloatingEdges/floating-edge-utils.ts diff --git a/examples/router.ts b/examples/router.ts index 881edc65..2af92005 100644 --- a/examples/router.ts +++ b/examples/router.ts @@ -61,6 +61,10 @@ export const routes: RouterOptions['routes'] = [ path: '/node-type-change', component: () => import('./src/NodeTypeChange/NodeTypeChangeExample.vue'), }, + { + path: '/floating-edges', + component: () => import('./src/FloatingEdges/FloatingEdges.vue'), + }, { path: '/overview', component: () => import('./src/Overview/Overview.vue'), diff --git a/examples/src/FloatingEdges/FloatingConnectionLine.vue b/examples/src/FloatingEdges/FloatingConnectionLine.vue new file mode 100644 index 00000000..b649eb51 --- /dev/null +++ b/examples/src/FloatingEdges/FloatingConnectionLine.vue @@ -0,0 +1,38 @@ + + diff --git a/examples/src/FloatingEdges/FloatingEdge.vue b/examples/src/FloatingEdges/FloatingEdge.vue new file mode 100644 index 00000000..139cbd2e --- /dev/null +++ b/examples/src/FloatingEdges/FloatingEdge.vue @@ -0,0 +1,47 @@ + + diff --git a/examples/src/FloatingEdges/FloatingEdges.vue b/examples/src/FloatingEdges/FloatingEdges.vue new file mode 100644 index 00000000..c9779753 --- /dev/null +++ b/examples/src/FloatingEdges/FloatingEdges.vue @@ -0,0 +1,39 @@ + + + diff --git a/examples/src/FloatingEdges/floating-edge-utils.ts b/examples/src/FloatingEdges/floating-edge-utils.ts new file mode 100644 index 00000000..c2a881ca --- /dev/null +++ b/examples/src/FloatingEdges/floating-edge-utils.ts @@ -0,0 +1,104 @@ +import { Position, MarkerType, XYPosition, GraphNode, Edge } from '@braks/vue-flow' + +// this helper function returns the intersection point +// of the line between the center of the intersectionNode and the target node +function getNodeIntersection(intersectionNode: GraphNode, targetNode: GraphNode): XYPosition { + // https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a + const { + dimensions: { width: intersectionNodeWidth, height: intersectionNodeHeight }, + position: intersectionNodePosition, + } = intersectionNode + const targetPosition = targetNode.position + + const w = intersectionNodeWidth / 2 + const h = intersectionNodeHeight / 2 + + const x2 = intersectionNodePosition.x + w + const y2 = intersectionNodePosition.y + h + const x1 = targetPosition.x + w + const y1 = targetPosition.y + h + + const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h) + const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h) + const a = 1 / (Math.abs(xx1) + Math.abs(yy1)) + const xx3 = a * xx1 + const yy3 = a * yy1 + const x = w * (xx3 + yy3) + x2 + const y = h * (-xx3 + yy3) + y2 + + return { x, y } +} + +// returns the position (top,right,bottom or right) passed node compared to the intersection point +function getEdgePosition(node: GraphNode, intersectionPoint: XYPosition) { + const n = { ...node.position, ...node.dimensions } + const nx = Math.round(n.x) + const ny = Math.round(n.y) + const px = Math.round(intersectionPoint.x) + const py = Math.round(intersectionPoint.y) + + if (px <= nx + 1) { + return Position.Left + } + if (px >= nx + n.width - 1) { + return Position.Right + } + if (py <= ny + 1) { + return Position.Top + } + if (py >= n.y + n.height - 1) { + return Position.Bottom + } + + return Position.Top +} + +// returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge +export function getEdgeParams(source: GraphNode, target: GraphNode) { + const sourceIntersectionPoint = getNodeIntersection(source, target) + const targetIntersectionPoint = getNodeIntersection(target, source) + + const sourcePos = getEdgePosition(source, sourceIntersectionPoint) + const targetPos = getEdgePosition(target, targetIntersectionPoint) + + return { + sx: sourceIntersectionPoint.x, + sy: sourceIntersectionPoint.y, + tx: targetIntersectionPoint.x, + ty: targetIntersectionPoint.y, + sourcePos, + targetPos, + } +} + +export function createElements() { + const win = typeof window !== 'undefined' ? window : ({} as any) + const elements = [] + const center = { x: win.innerWidth / 2, y: win.innerHeight / 2 } + + elements.push({ id: 'target', label: 'Target', position: center }) + + for (let i = 0; i < 8; i++) { + const degrees = i * (360 / 8) + const radians = degrees * (Math.PI / 180) + const x = 250 * Math.cos(radians) + center.x + const y = 250 * Math.sin(radians) + center.y + + elements.push({ id: `${i}`, label: 'Source', position: { x, y } }) + + elements.push({ + id: `edge-${i}`, + target: 'target', + source: `${i}`, + type: 'floating', + markerEnd: MarkerType.Arrow, + markerStart: { + id: 'markerstart', + type: MarkerType.Arrow, + orient: 'auto-start-reverse', + }, + } as Edge) + } + + return elements +}