I have a network that I want to draw with Konva (and the react-konva bindings). When positions update I want to animate the nodes in the network to their new positions while also animating the start and end position of the link that connects them.
I started with the following simple example, but can't seem to get a Line to animate in the same way that the nodes do.
Is there a way to fix this, or am I approaching it in the wrong way?
import React from "react";
import { Stage, Layer, Rect, Line } from "react-konva";
class Node extends React.Component {
componentDidUpdate() {
this.rect.to({
x: this.props.x,
y: this.props.y,
});
}
render() {
const { id } = this.props;
const color = id === "a" ? "blue" : "red";
return (
<Rect
ref={node => {
this.rect = node;
}}
width={5}
height={5}
fill={color}
/>
);
}
}
class Link extends React.Component {
componentDidUpdate() {
const x0 = 0;
const y0 = 0;
const x1 = 100;
const y1 = 100;
this.line.to({
x: x0,
y: y0,
points: [x1, y1, x0, y0],
});
}
render() {
const color = "#ccc";
return (
<Line
ref={node => {
this.line = node;
}}
stroke={color}
/>
);
}
}
class Graph extends React.Component {
constructor(props) {
super(props);
this.state = {
nodes: [{ id: "a", x: 0, y: 0 }, { id: "b", x: 200, y: 200 }],
links: [
{
source: "a",
target: "b",
},
],
};
}
handleClick = () => {
const nodes = this.state.nodes.map(node => {
const position = node.x === 0 ? { x: 200, y: 200 } : { x: 0, y: 0 };
return Object.assign({}, node, position);
});
this.setState({
nodes,
});
};
render() {
const { links, nodes } = this.state;
return (
<React.Fragment>
<Stage width={800} height={800}>
<Layer>
{nodes.map((node, index) => {
return (
<Node
key={`node-${index}`}
x={node.x}
y={node.y}
id={node.id}
/>
);
})}
</Layer>
<Layer>
{links.map(link => {
return (
<Link
source={nodes.find(node => node.id === link.source)}
target={nodes.find(node => node.id === link.target)}
/>
);
})}
</Layer>
</Stage>
<button onClick={this.handleClick}>Click me</button>
</React.Fragment>
);
}
}
export default Graph;