Skip to content

Commit

Permalink
fix: only render edges with visible source or target
Browse files Browse the repository at this point in the history
  • Loading branch information
doctoroyy committed Oct 26, 2021
1 parent 00e076e commit 84adeed
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 29 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-flow-renderer",
"version": "9.6.9",
"version": "9.6.10",
"engines": {
"node": ">=12"
},
Expand Down
17 changes: 12 additions & 5 deletions src/container/EdgeRenderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { memo, CSSProperties, useCallback } from 'react';

import { useStoreState } from '../../store/hooks';
import ConnectionLine from '../../components/ConnectionLine/index';
import { isEdge } from '../../utils/graph';
import { getNodeInside, isEdge } from '../../utils/graph';
import MarkerDefinitions from './MarkerDefinitions';
import { getEdgePositions, getHandle, isEdgeVisible, getSourceTargetNodes } from './utils';
import {
Expand Down Expand Up @@ -76,12 +76,12 @@ const Edge = ({
);

if (!sourceNode) {
console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`);
// console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`);
return null;
}

if (!targetNode) {
console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`);
// console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`);
return null;
}

Expand All @@ -104,12 +104,12 @@ const Edge = ({
const targetPosition = targetHandle ? targetHandle.position : Position.Top;

if (!sourceHandle) {
console.warn(`couldn't create edge for source handle id: ${sourceHandleId}; edge id: ${edge.id}`);
// console.warn(`couldn't create edge for source handle id: ${sourceHandleId}; edge id: ${edge.id}`);
return null;
}

if (!targetHandle) {
console.warn(`couldn't create edge for target handle id: ${targetHandleId}; edge id: ${edge.id}`);
// console.warn(`couldn't create edge for target handle id: ${targetHandleId}; edge id: ${edge.id}`);
return null;
}

Expand All @@ -122,6 +122,13 @@ const Edge = ({
targetPosition
);

const sourceNodeVisible = getNodeInside(sourceNode, { x: 0, y: 0, width, height }, transform, true)
const targetNodeVisible = getNodeInside(targetNode, { x: 0, y: 0, width, height }, transform, true)

if (!sourceNodeVisible && !targetNodeVisible) {
return null;
}

const isVisible = onlyRenderVisibleElements
? isEdgeVisible({
sourcePos: { x: sourceX, y: sourceY },
Expand Down
80 changes: 57 additions & 23 deletions src/utils/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export const parseNode = (node: Node, nodeExtent: NodeExtent): Node => {
type: node.type || 'default',
__rf: {
position: clampPosition(node.position, nodeExtent),
width: node.style?.width || null,
width: node.style?.width || null,
height: node.style?.height || null,
handleBounds: {},
isDragging: false,
Expand Down Expand Up @@ -212,6 +212,51 @@ export const graphPosToZoomedPos = ({ x, y }: XYPosition, [tx, ty, tScale]: Tran
y: y * tScale + ty,
});

export const getNodeInside = (
node: Node,
rect: Rect,
[tx, ty, tScale]: Transform = [0, 0, 1],
partially: boolean = false,
// set excludeNonSelectableNodes if you want to pay attention to the nodes "selectable" attribute
excludeNonSelectableNodes: boolean = false,
rBox?: Box,
): boolean => {
let _rBox = rBox;
if (!_rBox) {
_rBox = rectToBox({
x: (rect.x - tx) / tScale,
y: (rect.y - ty) / tScale,
width: rect.width / tScale,
height: rect.height / tScale,
});
}


const { selectable = true, __rf: { position, width, height, isDragging } } = node;

if (excludeNonSelectableNodes && !selectable) {
return false;
}

const nBox = rectToBox({ ...position, width, height });
const xOverlap = Math.max(0, Math.min(_rBox.x2, nBox.x2) - Math.max(_rBox.x, nBox.x));
const yOverlap = Math.max(0, Math.min(_rBox.y2, nBox.y2) - Math.max(_rBox.y, nBox.y));
const overlappingArea = Math.ceil(xOverlap * yOverlap);

if (width === null || height === null || isDragging) {
// nodes are initialized with width and height = null
return true;
}

if (partially) {
return overlappingArea > 0;
}

const area = width * height;

return overlappingArea >= area;
};

export const getNodesInside = (
nodes: Node[],
rect: Rect,
Expand All @@ -227,30 +272,19 @@ export const getNodesInside = (
height: rect.height / tScale,
});

return nodes.filter(({ selectable = true, __rf: { position, width, height, isDragging } }) => {
if (excludeNonSelectableNodes && !selectable) {
return false;
}

const nBox = rectToBox({ ...position, width, height });
const xOverlap = Math.max(0, Math.min(rBox.x2, nBox.x2) - Math.max(rBox.x, nBox.x));
const yOverlap = Math.max(0, Math.min(rBox.y2, nBox.y2) - Math.max(rBox.y, nBox.y));
const overlappingArea = Math.ceil(xOverlap * yOverlap);

if (width === null || height === null || isDragging) {
// nodes are initialized with width and height = null
return true;
}

if (partially) {
return overlappingArea > 0;
}
return nodes
.filter(node =>
getNodeInside(
node,
rect,
[tx, ty, tScale],
partially,
excludeNonSelectableNodes,
rBox
));
};

const area = width * height;

return overlappingArea >= area;
});
};

export const getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[] => {
const nodeIds = nodes.map((node) => node.id);
Expand Down

0 comments on commit 84adeed

Please sign in to comment.