chore(examples): add easy connect example

Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
braks
2023-04-03 08:54:32 +02:00
parent da6039fc35
commit adccf1b38e
6 changed files with 294 additions and 0 deletions

View File

@@ -118,6 +118,10 @@ export const routes: RouterOptions['routes'] = [
path: '/rgb',
component: () => import('./src/RGBFlow/RGBFlow.vue'),
},
{
path: '/easy-connect',
component: () => import('./src/EasyConnect/EasyConnect.vue'),
},
]
export const router = createRouter({

View File

@@ -0,0 +1,27 @@
<script lang="ts" setup>
import type { GraphNode } from '@vue-flow/core'
import { getStraightPath } from '@vue-flow/core'
import { computed } from '@vue/reactivity'
const props = defineProps<{ sourceNode: GraphNode; sourceX: number; sourceY: number; targetX: number; targetY: number }>()
const edgePath = computed(() =>
getStraightPath({
...props,
sourceX: props.sourceX - props.sourceNode.dimensions.width / 2,
}),
)
</script>
<template>
<g>
<path
:style="{
strokeWidth: 3,
stroke: 'black',
}"
fill="none"
:d="edgePath[0]"
/>
<circle :cx="targetX" :cy="targetY" fill="black" :r="3" stroke="black" :stroke-width="1.5" />
</g>
</template>

View File

@@ -0,0 +1,83 @@
<script lang="ts" setup>
import { Handle, Position, useVueFlow } from '@vue-flow/core'
import { computed } from 'vue'
const props = defineProps<{ id: string }>()
const { connectionStartHandle } = useVueFlow()
const isTarget = computed(() => connectionStartHandle.value && connectionStartHandle.value.nodeId !== props.id)
</script>
<template>
<div class="customNode">
<div
class="customNodeBody"
:style="{
borderStyle: isTarget ? 'dashed' : 'solid',
backgroundColor: isTarget ? '#ffcce3' : '#ccd9f6',
}"
>
<Handle class="targetHandle" style="z-index: 2" :position="Position.Right" type="source" connectable />
<Handle class="targetHandle" :style="{ zIndex: isTarget ? 3 : 1 }" :position="Position.Left" type="target" connectable />
{{ isTarget ? 'Drop here' : 'Drag to connect' }}
</div>
</div>
</template>
<style>
.customNodeBody {
width: 150px;
height: 80px;
border: 3px solid black;
position: relative;
overflow: hidden;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
}
.customNode:before {
content: '';
position: absolute;
top: -10px;
left: 50%;
height: 20px;
width: 40px;
transform: translate(-50%, 0);
background: #d6d5e6;
z-index: 1000;
line-height: 1;
border-radius: 4px;
color: #fff;
font-size: 9px;
border: 2px solid #222138;
}
.sourceHandle {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 0;
transform: none;
border: none;
opacity: 0;
}
.targetHandle {
width: 100%;
height: 100%;
background: blue;
position: absolute;
top: 0;
left: 0;
border-radius: 0;
transform: none;
border: none;
opacity: 0;
}
</style>

View File

@@ -0,0 +1,83 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap'
import type { Elements } from '@vue-flow/core'
import { MarkerType, VueFlow, useVueFlow } from '@vue-flow/core'
import CustomNode from './CustomNode.vue'
import CustomConnectionLine from './CustomConnectionLine.vue'
import FloatingEdge from './FloatingEdge.vue'
const { onConnect, addEdges } = useVueFlow()
const defaultEdgeOptions = {
style: { strokeWidth: 3, stroke: 'black' },
type: 'floating',
markerEnd: {
type: MarkerType.ArrowClosed,
color: 'black',
},
}
const elements = ref<Elements>([
{
id: '1',
type: 'custom',
position: { x: 0, y: 0 },
},
{
id: '2',
type: 'custom',
position: { x: 250, y: 320 },
},
{
id: '3',
type: 'custom',
position: { x: 40, y: 300 },
},
{
id: '4',
type: 'custom',
position: { x: 300, y: 0 },
},
])
onConnect((params) => {
console.log('connecting')
addEdges([params])
})
</script>
<template>
<div style="height: 100vh">
<VueFlow
v-model="elements"
:elevate-nodes-on-select="false"
class="vue-flow-basic-example"
:default-zoom="1.5"
:default-edge-options="defaultEdgeOptions"
:min-zoom="0.2"
:max-zoom="4"
>
<Background pattern-color="#aaa" :gap="8" />
<MiniMap />
<Controls />
<template #node-custom="props">
<CustomNode :id="props.id" />
</template>
<template #edge-floating="fProps">
<FloatingEdge v-bind="fProps" />
</template>
<template #connection-line="cProps">
<CustomConnectionLine v-bind="cProps" />
</template>
</VueFlow>
</div>
</template>

View File

@@ -0,0 +1,24 @@
<script lang="ts" setup>
import type { GraphNode } from '@vue-flow/core'
import { getStraightPath } from '@vue-flow/core'
import { computed } from 'vue'
import { getEdgeParams } from './utils'
const props = defineProps<{ id: string; sourceNode: GraphNode; targetNode: GraphNode; markerEnd: string; style: any }>()
const edgeParams = computed(() => getEdgeParams(props.sourceNode, props.targetNode))
const edgePath = computed(() =>
getStraightPath({
sourceX: edgeParams.value.sx,
sourceY: edgeParams.value.sy,
targetX: edgeParams.value.tx,
targetY: edgeParams.value.ty,
}),
)
</script>
<template>
<path :id="id" class="vue-flow__edge-path" :d="edgePath[0]" :marker-end="markerEnd" :style="style" />
</template>

View File

@@ -0,0 +1,73 @@
import type { GraphNode, XYPosition } from '@vue-flow/core'
import { Position } from '@vue-flow/core'
// 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) {
// 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 },
computedPosition: intersectionNodePosition,
} = intersectionNode
const targetPosition = targetNode.computedPosition
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.computedPosition, ...node }
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.dimensions.width - 1) {
return Position.Right
}
if (py <= ny + 1) {
return Position.Top
}
if (py >= n.y + n.dimensions.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,
}
}