Files
xyflow/src/EdgeRenderer/index.js
T

117 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { memo, useContext } from 'react';
import { GraphContext } from '../GraphContext';
import { ConnectionContext } from '../ConnectionContext';
import ConnectionLine from '../ConnectionLine';
import { isEdge } from '../graph-utils';
function getEdgePositions(sourceNode, targetNode) {
const hasSourceHandle = !!sourceNode.__rg.handleBounds.source;
const hasTargetHandle = !!targetNode.__rg.handleBounds.target;
const sourceHandleX = hasSourceHandle ?
sourceNode.__rg.handleBounds.source.x + (sourceNode.__rg.handleBounds.source.width / 2) :
sourceNode.__rg.width / 2;
const sourceHandleY = hasSourceHandle ?
sourceNode.__rg.handleBounds.source.y + (sourceNode.__rg.handleBounds.source.height / 2) :
sourceNode.__rg.height;
const sourceX = sourceNode.__rg.position.x + sourceHandleX;
const sourceY = sourceNode.__rg.position.y + sourceHandleY;
const targetHandleX = hasTargetHandle ?
targetNode.__rg.handleBounds.target.x + (targetNode.__rg.handleBounds.target.width / 2) :
targetNode.__rg.width / 2;
const targetHandleY = hasTargetHandle ?
targetNode.__rg.handleBounds.target.y + (targetNode.__rg.handleBounds.target.height / 2) :
0;
const targetX = targetNode.__rg.position.x + targetHandleX;
const targetY = targetNode.__rg.position.y + targetHandleY;
return {
sourceX, sourceY, targetX, targetY
};
}
function renderEdge(e, props, graphContext) {
const edgeType = e.type || 'default';
const sourceNode = graphContext.state.nodes.find(n => n.id === e.source);
const targetNode = graphContext.state.nodes.find(n => n.id === e.target);
if (!sourceNode) {
throw new Error(`couldn't create edge for source id: ${e.source}`);
}
if (!targetNode) {
throw new Error(`couldn't create edge for target id: ${e.target}`);
}
const EdgeComponent = props.edgeTypes[edgeType] || props.edgeTypes.default;
const { sourceX, sourceY, targetX, targetY } = getEdgePositions(sourceNode, targetNode);
const selected = graphContext.state.selectedElements
.filter(isEdge)
.find(elm => elm.source === e.source && elm.target === e.target);
return (
<EdgeComponent
key={e.id}
id={e.id}
type={e.type}
onClick={props.onElementClick}
selected={selected}
dispatch={graphContext.dispatch}
animated={e.animated}
style={e.style}
source={e.source}
target={e.target}
sourceX={sourceX}
sourceY={sourceY}
targetX={targetX}
targetY={targetY}
/>
);
}
const EdgeRenderer = memo((props) => {
const graphContext = useContext(GraphContext);
const { position, sourceId : connectionSourceId } = useContext(ConnectionContext);
const {
width, height, connectionLineStyle, connectionLineType
} = props;
if (!width) {
return null;
}
const { transform, edges, nodes } = graphContext.state;
const transformStyle = `translate(${transform[0]},${transform[1]}) scale(${transform[2]})`;
return (
<svg
width={width}
height={height}
className="react-graph__edges"
>
<g transform={transformStyle}>
{edges.map(e => renderEdge(e, props, graphContext))}
{connectionSourceId && (
<ConnectionLine
nodes={nodes}
connectionSourceId={connectionSourceId}
connectionPositionX={position.x}
connectionPositionY={position.y}
transform={transform}
connectionLineStyle={connectionLineStyle}
connectionLineType={connectionLineType}
/>
)}
</g>
</svg>
);
});
export default EdgeRenderer;