Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'v10' into refactor/nodes-edges-state
- Loading branch information
Showing
27 changed files
with
691 additions
and
356 deletions.
There are no files selected for viewing
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
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 |
---|---|---|
|
@@ -21,3 +21,5 @@ | |
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
/src_oldapi |
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,42 @@ | ||
import { FC } from 'react'; | ||
import { getBezierPath, ConnectionLineComponentProps, Node } from 'react-flow-renderer'; | ||
|
||
import { getEdgeParams } from './utils'; | ||
|
||
const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({ | ||
targetX, | ||
targetY, | ||
sourcePosition, | ||
targetPosition, | ||
sourceNode, | ||
}) => { | ||
if (!sourceNode) { | ||
return null; | ||
} | ||
|
||
const targetNode = { | ||
id: 'connection-target', | ||
width: 1, | ||
height: 1, | ||
position: { x: targetX, y: targetY }, | ||
} as Node; | ||
|
||
const { sx, sy } = getEdgeParams(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,36 @@ | ||
import { FC, useMemo, CSSProperties } from 'react'; | ||
import { EdgeProps, useStore, getBezierPath, ReactFlowState } from 'react-flow-renderer'; | ||
|
||
import { getEdgeParams } from './utils'; | ||
|
||
const nodeSelector = (s: ReactFlowState) => s.nodes; | ||
|
||
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, style }) => { | ||
const nodes = useStore(nodeSelector); | ||
|
||
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 } = getEdgeParams(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} 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,65 @@ | ||
import { useState, useCallback } from 'react'; | ||
|
||
import ReactFlow, { | ||
addEdge, | ||
Background, | ||
OnLoadParams, | ||
EdgeTypesType, | ||
Node, | ||
Connection, | ||
Edge, | ||
applyNodeChanges, | ||
applyEdgeChanges, | ||
NodeChange, | ||
EdgeChange, | ||
} from 'react-flow-renderer'; | ||
|
||
import './style.css'; | ||
|
||
import FloatingEdge from './FloatingEdge'; | ||
import FloatingConnectionLine from './FloatingConnectionLine'; | ||
import { createElements } from './utils'; | ||
|
||
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView(); | ||
|
||
const { nodes: initialNodes, edges: initialEdges } = createElements(); | ||
|
||
const edgeTypes: EdgeTypesType = { | ||
floating: FloatingEdge, | ||
}; | ||
|
||
const FloatingEdges = () => { | ||
const [nodes, setNodes] = useState<Node[]>(initialNodes); | ||
const [edges, setEdges] = useState<Edge[]>(initialEdges); | ||
|
||
const onConnect = useCallback((params: Edge | Connection) => { | ||
setEdges((eds) => addEdge(params, eds)); | ||
}, []); | ||
|
||
const onNodesChange = useCallback((changes: NodeChange[]) => { | ||
setNodes((ns) => applyNodeChanges(changes, ns)); | ||
}, []); | ||
|
||
const onEdgesChange = useCallback((changes: EdgeChange[]) => { | ||
setEdges((es) => applyEdgeChanges(changes, es)); | ||
}, []); | ||
|
||
return ( | ||
<div className="floatingedges"> | ||
<ReactFlow | ||
nodes={nodes} | ||
edges={edges} | ||
onNodesChange={onNodesChange} | ||
onEdgesChange={onEdgesChange} | ||
onConnect={onConnect} | ||
onLoad={onLoad} | ||
edgeTypes={edgeTypes} | ||
connectionLineComponent={FloatingConnectionLine} | ||
> | ||
<Background /> | ||
</ReactFlow> | ||
</div> | ||
); | ||
}; | ||
|
||
export default FloatingEdges; |
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,9 @@ | ||
.floatingedges { | ||
flex-direction: column; | ||
display: flex; | ||
height: 100%; | ||
} | ||
|
||
.floatingedges .react-flow__handle { | ||
opacity: 0; | ||
} |
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,106 @@ | ||
import { Position, ArrowHeadType, XYPosition, Node, Edge } from 'react-flow-renderer'; | ||
|
||
// 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 | ||
|
||
const { | ||
width: intersectionNodeWidth, | ||
height: intersectionNodeHeight, | ||
position: intersectionNodePosition, | ||
} = intersectionNode; | ||
const targetPosition = targetNode.position; | ||
|
||
const w = (intersectionNodeWidth ?? 0) / 2; | ||
const h = (intersectionNodeHeight ?? 0) / 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: Node, intersectionPoint: XYPosition) { | ||
const n = { ...node.position, ...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.width ?? 0) - 1) { | ||
return Position.Right; | ||
} | ||
if (py <= ny + 1) { | ||
return Position.Top; | ||
} | ||
if (py >= n.y + (n.height ?? 0) - 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: Node, target: Node) { | ||
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, | ||
}; | ||
} | ||
|
||
type NodesAndEdges = { | ||
nodes: Node[]; | ||
edges: Edge[]; | ||
}; | ||
|
||
export function createElements(): NodesAndEdges { | ||
const nodes: Node[] = []; | ||
const edges: Edge[] = []; | ||
|
||
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 }; | ||
|
||
nodes.push({ id: 'target', data: { 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; | ||
|
||
nodes.push({ id: `${i}`, data: { label: 'Source' }, position: { x, y } }); | ||
|
||
edges.push({ | ||
id: `edge-${i}`, | ||
target: 'target', | ||
source: `${i}`, | ||
type: 'floating', | ||
}); | ||
} | ||
|
||
return { nodes, edges }; | ||
} |
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
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
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
Oops, something went wrong.