refactor(edges): only redraw moved edges

This commit is contained in:
moklick
2019-07-31 16:29:04 +02:00
parent ec7231e42d
commit 6e71591cb8
9 changed files with 433 additions and 400 deletions
+6 -5
View File
@@ -1,16 +1,17 @@
import React, { useContext, memo } from 'react';
import React, { memo } from 'react';
import cx from 'classnames';
import { GraphContext } from '../../GraphContext';
import { setSelectedElements } from '../../state/actions';
import { isEdge } from '../../graph-utils';
const isInput = e => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName);
export default EdgeComponent => memo((props) => {
const { state, dispatch } = useContext(GraphContext);
const { source, target, animated, type, onClick } = props;
const selected = state.selectedElements
const {
source, target, animated, type,
dispatch, selectedElements, onClick
} = props;
const selected = selectedElements
.filter(e => isEdge(e))
.find(e => e.source === source && e.target === target);
const edgeClasses = cx('react-graph__edge', { selected, animated: animated });
+68 -63
View File
@@ -1,73 +1,78 @@
import React, { PureComponent } from 'react';
import React, { memo, useContext } from 'react';
import { Consumer } from '../GraphContext';
import { GraphContext } from '../GraphContext';
import ConnectionLine from '../ConnectionLine';
class EdgeRenderer extends PureComponent {
renderEdge(e, nodes, onElementClick) {
const edgeType = e.type || 'default';
const sourceNode = nodes.find(n => n.id === e.source);
const targetNode = nodes.find(n => n.id === e.target);
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 = this.props.edgeTypes[edgeType] || this.props.edgeTypes.default;
return (
<EdgeComponent
key={`${e.source}-${e.target}`}
sourceNode={sourceNode}
targetNode={targetNode}
onClick={onElementClick}
{...e}
/>
);
if (!sourceNode) {
throw new Error(`couldn't create edge for source id: ${e.source}`);
}
render() {
const {
width, height, onElementClick,
connectionLineStyle, connectionLineType
} = this.props;
if (!width) {
return null;
}
return (
<Consumer>
{({ state }) => (
<svg
width={width}
height={height}
className="react-graph__edges"
>
<g
transform={`translate(${state.transform[0]},${state.transform[1]}) scale(${state.transform[2]})`}
>
{state.edges.map(e => this.renderEdge(e, state.nodes, onElementClick))}
{state.connectionSourceId && (
<ConnectionLine
nodes={state.nodes}
connectionSourceId={state.connectionSourceId}
connectionPosition={state.connectionPosition}
transform={state.transform}
connectionLineStyle={connectionLineStyle}
connectionLineType={connectionLineType}
/>
)}
</g>
</svg>
)}
</Consumer>
);
if (!targetNode) {
throw new Error(`couldn't create edge for target id: ${e.target}`);
}
const EdgeComponent = props.edgeTypes[edgeType] || props.edgeTypes.default;
return (
<EdgeComponent
key={`${e.source}-${e.target}`}
type={e.type}
sourceNode={sourceNode}
targetNode={targetNode}
onClick={props.onElementClick}
selectedElements={graphContext.state.selectedElements}
dispatch={graphContext.dispatch}
animated={e.animated}
style={e.style}
source={e.source}
target={e.target}
sourceNodeX={sourceNode.__rg.position.x}
sourceNodeY={sourceNode.__rg.position.y}
targetNodeX={targetNode.__rg.position.x}
targeteNodeY={targetNode.__rg.position.y}
/>
);
}
const EdgeRenderer = memo((props) => {
const graphContext = useContext(GraphContext);
const {
width, height, connectionLineStyle, connectionLineType
} = props;
if (!width) {
return null;
}
const { transform, edges, nodes, connectionSourceId, connectionPosition } = 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}
connectionPosition={connectionPosition}
transform={transform}
connectionLineStyle={connectionLineStyle}
connectionLineType={connectionLineType}
/>
)}
</g>
</svg>
);
});
export default EdgeRenderer;
+2 -6
View File
@@ -1,8 +1,6 @@
import React, { memo, useContext } from 'react';
import React, { memo } from 'react';
import cx from 'classnames';
import NodeIdContext from '../NodeIdContext'
import { GraphContext } from '../../GraphContext';
import { setConnecting, setConnectionPos } from '../../state/actions';
function onMouseDown(evt, { nodeId, dispatch, onConnect, isTarget }) {
@@ -37,9 +35,7 @@ function onMouseDown(evt, { nodeId, dispatch, onConnect, isTarget }) {
document.addEventListener('mouseup', onMouseUp)
}
export default memo(({ source, target, className = null, ...rest }) => {
const nodeId = useContext(NodeIdContext);
const { dispatch, onConnect } = useContext(GraphContext);
export default memo(({ source, target, nodeId, onConnect, dispatch, className = null, ...rest }) => {
const handleClasses = cx(
'react-graph__handle',
className,
+17 -2
View File
@@ -1,5 +1,20 @@
import React from 'react';
import React, { memo, useContext } from 'react';
import BaseHandle from './BaseHandle';
import NodeIdContext from '../NodeIdContext'
import { GraphContext } from '../../GraphContext';
export default props => <BaseHandle source {...props} />;
export default memo((props) => {
const nodeId = useContext(NodeIdContext);
const { dispatch, onConnect } = useContext(GraphContext);
return (
<BaseHandle
source
nodeId={nodeId}
dispatch={dispatch}
onConnect={onConnect}
{...props}
/>
);
});
+17 -2
View File
@@ -1,6 +1,21 @@
import React from 'react';
import React, { memo, useContext } from 'react';
import BaseHandle from './BaseHandle';
import { GraphContext } from '../../GraphContext';
import NodeIdContext from '../NodeIdContext'
export default props => <BaseHandle target {...props} />;
export default memo((props) => {
const nodeId = useContext(NodeIdContext);
const { dispatch, onConnect } = useContext(GraphContext);
return (
<BaseHandle
target
nodeId={nodeId}
dispatch={dispatch}
onConnect={onConnect}
{...props}
/>
);
});
+2 -3
View File
@@ -32,13 +32,12 @@ function renderNode(d, props, graphContext) {
const NodeRenderer = memo((props) => {
const graphContext = useContext(GraphContext);
const { transform, nodes } = graphContext.state;
const transformStyle = { transform : `translate(${transform[0]}px,${transform[1]}px) scale(${transform[2]})` };
return (
<div
className="react-graph__nodes"
style={{
transform: `translate(${transform[0]}px,${transform[1]}px) scale(${transform[2]})`
}}
style={transformStyle}
>
{nodes.map(d => renderNode(d, props, graphContext))}
</div>