refactor(floating-edges-example): comments and cleanup
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { getBezierPath, ConnectionLineComponentProps } from 'react-flow-renderer';
|
import { getBezierPath, ConnectionLineComponentProps, Node } from 'react-flow-renderer';
|
||||||
|
|
||||||
import { getArrow } from './utils';
|
import { getEdgeParams } from './utils';
|
||||||
|
|
||||||
const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({
|
const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({
|
||||||
targetX,
|
targetX,
|
||||||
@@ -14,8 +14,12 @@ const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetNode = { __rf: { width: 1, height: 1, position: { x: targetX, y: targetY } } };
|
const targetNode = {
|
||||||
const { sx, sy } = getArrow(sourceNode, targetNode);
|
id: 'connection-target',
|
||||||
|
__rf: { width: 1, height: 1, position: { x: targetX, y: targetY } },
|
||||||
|
} as Node;
|
||||||
|
|
||||||
|
const { sx, sy } = getEdgeParams(sourceNode, targetNode);
|
||||||
const d = getBezierPath({
|
const d = getBezierPath({
|
||||||
sourceX: sx,
|
sourceX: sx,
|
||||||
sourceY: sy,
|
sourceY: sy,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FC, useMemo, CSSProperties } from 'react';
|
import { FC, useMemo, CSSProperties } from 'react';
|
||||||
import { EdgeProps, getMarkerEnd, useStoreState, getBezierPath } from 'react-flow-renderer';
|
import { EdgeProps, getMarkerEnd, useStoreState, getBezierPath } from 'react-flow-renderer';
|
||||||
|
|
||||||
import { getArrow } from './utils';
|
import { getEdgeParams } from './utils';
|
||||||
|
|
||||||
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, arrowHeadType, markerEndId, style }) => {
|
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, arrowHeadType, markerEndId, style }) => {
|
||||||
const nodes = useStoreState((state) => state.nodes);
|
const nodes = useStoreState((state) => state.nodes);
|
||||||
@@ -14,7 +14,7 @@ const FloatingEdge: FC<EdgeProps> = ({ id, source, target, arrowHeadType, marker
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { sx, sy, tx, ty, sourcePos, targetPos } = getArrow(sourceNode, targetNode);
|
const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(sourceNode, targetNode);
|
||||||
|
|
||||||
const d = getBezierPath({
|
const d = getBezierPath({
|
||||||
sourceX: sx,
|
sourceX: sx,
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import React, { useState } from 'react';
|
|||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
removeElements,
|
removeElements,
|
||||||
addEdge,
|
addEdge,
|
||||||
MiniMap,
|
|
||||||
Controls,
|
|
||||||
Background,
|
Background,
|
||||||
OnLoadParams,
|
OnLoadParams,
|
||||||
EdgeTypesType,
|
EdgeTypesType,
|
||||||
@@ -14,6 +12,8 @@ import ReactFlow, {
|
|||||||
ArrowHeadType,
|
ArrowHeadType,
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
|
|
||||||
|
import './style.css';
|
||||||
|
|
||||||
import FloatingEdge from './FloatingEdge';
|
import FloatingEdge from './FloatingEdge';
|
||||||
import FloatingConnectionLine from './FloatingConnectionLine';
|
import FloatingConnectionLine from './FloatingConnectionLine';
|
||||||
import { createElements } from './utils';
|
import { createElements } from './utils';
|
||||||
@@ -30,22 +30,23 @@ const NodeAsHandleFlow = () => {
|
|||||||
const [elements, setElements] = useState<Elements>(initialElements);
|
const [elements, setElements] = useState<Elements>(initialElements);
|
||||||
|
|
||||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||||
|
|
||||||
const onConnect = (params: Connection | Edge) =>
|
const onConnect = (params: Connection | Edge) =>
|
||||||
setElements((els) => addEdge({ ...params, type: 'floating', arrowHeadType: ArrowHeadType.Arrow }, els));
|
setElements((els) => addEdge({ ...params, type: 'floating', arrowHeadType: ArrowHeadType.Arrow }, els));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactFlow
|
<div className="floatingedges">
|
||||||
elements={elements}
|
<ReactFlow
|
||||||
onElementsRemove={onElementsRemove}
|
elements={elements}
|
||||||
onConnect={onConnect}
|
onElementsRemove={onElementsRemove}
|
||||||
onLoad={onLoad}
|
onConnect={onConnect}
|
||||||
edgeTypes={edgeTypes}
|
onLoad={onLoad}
|
||||||
connectionLineComponent={FloatingConnectionLine}
|
edgeTypes={edgeTypes}
|
||||||
>
|
connectionLineComponent={FloatingConnectionLine}
|
||||||
<MiniMap />
|
>
|
||||||
<Controls />
|
<Background />
|
||||||
<Background />
|
</ReactFlow>
|
||||||
</ReactFlow>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
.floatingedges {
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floatingedges .react-flow__handle {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
import { Position, ArrowHeadType, Node } from 'react-flow-renderer';
|
import { Position, ArrowHeadType, Node, XYPosition } from 'react-flow-renderer';
|
||||||
|
|
||||||
function getNodeIntersection(source: Node, target: Node) {
|
// this helper function returns the intersection point
|
||||||
|
// of the line between the center of the intersectionNode and the target node
|
||||||
|
function getNodeIntersection(intersectionNode: Node, targetNode: Node): XYPosition {
|
||||||
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a
|
// 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 {
|
||||||
const targetPosition = target.__rf.position;
|
width: intersectionNodeWidth,
|
||||||
|
height: intersectionNodeHeight,
|
||||||
|
position: intersectionNodePosition,
|
||||||
|
} = intersectionNode.__rf;
|
||||||
|
const targetPosition = targetNode.__rf.position;
|
||||||
|
|
||||||
const w = sourceWidth / 2;
|
const w = intersectionNodeWidth / 2;
|
||||||
const h = sourceHeight / 2;
|
const h = intersectionNodeHeight / 2;
|
||||||
|
|
||||||
const x2 = sourcePosition.x + w;
|
const x2 = intersectionNodePosition.x + w;
|
||||||
const y2 = sourcePosition.y + h;
|
const y2 = intersectionNodePosition.y + h;
|
||||||
const x1 = targetPosition.x;
|
const x1 = targetPosition.x + w;
|
||||||
const y1 = targetPosition.y;
|
const y1 = targetPosition.y + h;
|
||||||
|
|
||||||
const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h);
|
const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h);
|
||||||
const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h);
|
const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h);
|
||||||
@@ -21,15 +27,16 @@ function getNodeIntersection(source: Node, target: Node) {
|
|||||||
const x = w * (xx3 + yy3) + x2;
|
const x = w * (xx3 + yy3) + x2;
|
||||||
const y = h * (-xx3 + yy3) + y2;
|
const y = h * (-xx3 + yy3) + y2;
|
||||||
|
|
||||||
return [x, y];
|
return { x, y };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEdgePosition(node: Node, x: number, y: number) {
|
// returns the position (top,right,bottom or right) passed node compared to the intersection point
|
||||||
|
function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
|
||||||
const n = { ...node.__rf.position, ...node.__rf };
|
const n = { ...node.__rf.position, ...node.__rf };
|
||||||
const nx = Math.round(n.x);
|
const nx = Math.round(n.x);
|
||||||
const ny = Math.round(n.y);
|
const ny = Math.round(n.y);
|
||||||
const px = Math.round(x);
|
const px = Math.round(intersectionPoint.x);
|
||||||
const py = Math.round(y);
|
const py = Math.round(intersectionPoint.y);
|
||||||
|
|
||||||
if (px <= nx + 1) {
|
if (px <= nx + 1) {
|
||||||
return Position.Left;
|
return Position.Left;
|
||||||
@@ -47,19 +54,19 @@ function getEdgePosition(node: Node, x: number, y: number) {
|
|||||||
return Position.Top;
|
return Position.Top;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getArrow(source: any, target: any) {
|
// returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge
|
||||||
const [sx, sy] = getNodeIntersection(source, target);
|
export function getEdgeParams(source: Node, target: Node) {
|
||||||
const [tx, ty] = getNodeIntersection(target, source);
|
const sourceIntersectionPoint = getNodeIntersection(source, target);
|
||||||
|
const targetIntersectionPoint = getNodeIntersection(target, source);
|
||||||
|
|
||||||
const sourcePos = getEdgePosition(source, sx, sy);
|
const sourcePos = getEdgePosition(source, sourceIntersectionPoint);
|
||||||
const targetPos = getEdgePosition(target, tx, ty);
|
const targetPos = getEdgePosition(target, targetIntersectionPoint);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sx,
|
sx: sourceIntersectionPoint.x,
|
||||||
sy,
|
sy: sourceIntersectionPoint.y,
|
||||||
tx,
|
tx: targetIntersectionPoint.x,
|
||||||
ty,
|
ty: targetIntersectionPoint.y,
|
||||||
label: null,
|
|
||||||
sourcePos,
|
sourcePos,
|
||||||
targetPos,
|
targetPos,
|
||||||
};
|
};
|
||||||
@@ -69,7 +76,7 @@ export function createElements() {
|
|||||||
const elements = [];
|
const elements = [];
|
||||||
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
|
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
|
||||||
|
|
||||||
elements.push({ id: 'source', data: { label: 'Source', isTarget: false }, position: center });
|
elements.push({ id: 'target', data: { label: 'Target' }, position: center });
|
||||||
|
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
const degrees = i * (360 / 8);
|
const degrees = i * (360 / 8);
|
||||||
@@ -77,17 +84,15 @@ export function createElements() {
|
|||||||
const x = 250 * Math.cos(radians) + center.x;
|
const x = 250 * Math.cos(radians) + center.x;
|
||||||
const y = 250 * Math.sin(radians) + center.y;
|
const y = 250 * Math.sin(radians) + center.y;
|
||||||
|
|
||||||
elements.push({ id: `${i}`, data: { label: 'Target', isTarget: true }, position: { x, y } });
|
elements.push({ id: `${i}`, data: { label: 'Source' }, position: { x, y } });
|
||||||
|
|
||||||
if (i % 2 === 0) {
|
elements.push({
|
||||||
elements.push({
|
id: `edge-${i}`,
|
||||||
id: `source-${i}`,
|
target: 'target',
|
||||||
source: 'source',
|
source: `${i}`,
|
||||||
target: `${i}`,
|
type: 'floating',
|
||||||
type: 'floating',
|
arrowHeadType: ArrowHeadType.Arrow,
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements;
|
return elements;
|
||||||
|
|||||||
Reference in New Issue
Block a user