forked from xyflow/xyflow
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(floating-edge-example): cleanup
- Loading branch information
Showing
9 changed files
with
224 additions
and
250 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { FC } from 'react'; | ||
import { getBezierPath, ConnectionLineComponentProps } from 'react-flow-renderer'; | ||
|
||
import { getArrow } from './utils'; | ||
|
||
const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({ | ||
targetX, | ||
targetY, | ||
sourcePosition, | ||
targetPosition, | ||
sourceNode, | ||
}) => { | ||
if (!sourceNode) { | ||
return null; | ||
} | ||
|
||
const targetNode = { __rf: { width: 1, height: 1, position: { x: targetX, y: targetY } } }; | ||
const { sx, sy } = getArrow(sourceNode, targetNode); | ||
const d = getBezierPath({ | ||
sourceX: sx, | ||
sourceY: sy, | ||
sourcePosition, | ||
targetPosition, | ||
targetX, | ||
targetY, | ||
}); | ||
|
||
return ( | ||
<g> | ||
<path fill="none" stroke="#222" strokeWidth={1.5} className="animated" d={d} /> | ||
<circle cx={targetX} cy={targetY} fill="#fff" r={3} stroke="#222" strokeWidth={1.5} /> | ||
</g> | ||
); | ||
}; | ||
|
||
export default FloatingConnectionLine; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { FC, useMemo, CSSProperties } from 'react'; | ||
import { EdgeProps, getMarkerEnd, useStoreState, getBezierPath } from 'react-flow-renderer'; | ||
|
||
import { getArrow } from './utils'; | ||
|
||
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, arrowHeadType, markerEndId, style }) => { | ||
const nodes = useStoreState((state) => state.nodes); | ||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId); | ||
|
||
const sourceNode = useMemo(() => nodes.find((n) => n.id === source), [source, nodes]); | ||
const targetNode = useMemo(() => nodes.find((n) => n.id === target), [target, nodes]); | ||
|
||
if (!sourceNode || !targetNode) { | ||
return null; | ||
} | ||
|
||
const { sx, sy, tx, ty, sourcePos, targetPos } = getArrow(sourceNode, targetNode); | ||
|
||
const d = getBezierPath({ | ||
sourceX: sx, | ||
sourceY: sy, | ||
sourcePosition: sourcePos, | ||
targetPosition: targetPos, | ||
targetX: tx, | ||
targetY: ty, | ||
}); | ||
|
||
return ( | ||
<g className="react-flow__connection"> | ||
<path id={id} className="react-flow__edge-path" d={d} markerEnd={markerEnd} style={style as CSSProperties} /> | ||
</g> | ||
); | ||
}; | ||
|
||
export default FloatingEdge; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React, { useState } from 'react'; | ||
|
||
import ReactFlow, { | ||
removeElements, | ||
addEdge, | ||
MiniMap, | ||
Controls, | ||
Background, | ||
OnLoadParams, | ||
EdgeTypesType, | ||
Elements, | ||
Connection, | ||
Edge, | ||
ArrowHeadType, | ||
} from 'react-flow-renderer'; | ||
|
||
import FloatingEdge from './FloatingEdge'; | ||
import FloatingConnectionLine from './FloatingConnectionLine'; | ||
import { createElements } from './utils'; | ||
|
||
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView(); | ||
|
||
const initialElements: Elements = createElements(); | ||
|
||
const edgeTypes: EdgeTypesType = { | ||
floating: FloatingEdge, | ||
}; | ||
|
||
const NodeAsHandleFlow = () => { | ||
const [elements, setElements] = useState<Elements>(initialElements); | ||
|
||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els)); | ||
const onConnect = (params: Connection | Edge) => | ||
setElements((els) => addEdge({ ...params, type: 'floating', arrowHeadType: ArrowHeadType.Arrow }, els)); | ||
|
||
return ( | ||
<ReactFlow | ||
elements={elements} | ||
onElementsRemove={onElementsRemove} | ||
onConnect={onConnect} | ||
onLoad={onLoad} | ||
edgeTypes={edgeTypes} | ||
connectionLineComponent={FloatingConnectionLine} | ||
> | ||
<MiniMap /> | ||
<Controls /> | ||
<Background /> | ||
</ReactFlow> | ||
); | ||
}; | ||
|
||
export default NodeAsHandleFlow; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { Position, ArrowHeadType, Node } from 'react-flow-renderer'; | ||
|
||
function getNodeIntersection(source: Node, target: Node) { | ||
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a | ||
const { width: sourceWidth, height: sourceHeight, position: sourcePosition } = source.__rf; | ||
const targetPosition = target.__rf.position; | ||
|
||
const w = sourceWidth / 2; | ||
const h = sourceHeight / 2; | ||
|
||
const x2 = sourcePosition.x + w; | ||
const y2 = sourcePosition.y + h; | ||
const x1 = targetPosition.x; | ||
const y1 = targetPosition.y; | ||
|
||
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]; | ||
} | ||
|
||
function getEdgePosition(node: Node, x: number, y: number) { | ||
const n = { ...node.__rf.position, ...node.__rf }; | ||
const nx = Math.round(n.x); | ||
const ny = Math.round(n.y); | ||
const px = Math.round(x); | ||
const py = Math.round(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; | ||
} | ||
|
||
export function getArrow(source: any, target: any) { | ||
const [sx, sy] = getNodeIntersection(source, target); | ||
const [tx, ty] = getNodeIntersection(target, source); | ||
|
||
const sourcePos = getEdgePosition(source, sx, sy); | ||
const targetPos = getEdgePosition(target, tx, ty); | ||
|
||
return { | ||
sx, | ||
sy, | ||
tx, | ||
ty, | ||
label: null, | ||
sourcePos, | ||
targetPos, | ||
}; | ||
} | ||
|
||
export function createElements() { | ||
const elements = []; | ||
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 }; | ||
|
||
elements.push({ id: 'source', data: { label: 'Source', isTarget: false }, 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}`, data: { label: 'Target', isTarget: true }, position: { x, y } }); | ||
|
||
if (i % 2 === 0) { | ||
elements.push({ | ||
id: `source-${i}`, | ||
source: 'source', | ||
target: `${i}`, | ||
type: 'floating', | ||
arrowHeadType: ArrowHeadType.Arrow, | ||
}); | ||
} | ||
} | ||
|
||
return elements; | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.