【问题标题】:Animating Line position in KonvaKonva 中的动画线位置
【发布时间】:2019-12-09 03:58:20
【问题描述】:

我有一个我想用 Konva(和 react-konva 绑定)绘制的网络。当位置更新时,我想将网络中的节点动画到它们的新位置,同时动画连接它们的链接的开始和结束位置。

我从以下简单示例开始,但似乎无法以与节点相同的方式使线动画化。

有没有办法解决这个问题,还是我以错误的方式接近它?

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;

【问题讨论】:

    标签: javascript konvajs react-konva


    【解决方案1】:

    您可能需要为points 属性设置初始值以获得更好的补间效果。 此外,您没有在Link 组件中使用sourcetarget。您应该使用该道具来计算动画。

    import React from "react";
    import { render } from "react-dom";
    import { Stage, Layer, Rect, Line } from "react-konva";
    
    class Node extends React.Component {
      componentDidMount() {
        this.rect.setAttrs({
          x: this.props.x,
          y: this.props.y
        });
      }
      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 {
      componentDidMount() {
        // set initial value:
        const { source, target } = this.props;
    
        console.log(source, target);
        this.line.setAttrs({
          points: [source.x, source.y, target.x, target.y]
        });
      }
      componentDidUpdate() {
        this.animate();
      }
    
      animate() {
        const { source, target } = this.props;
    
        this.line.to({
          points: [source.x, source.y, target.x, target.y]
        });
      }
    
      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={300}>
              <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>
        );
      }
    }
    
    render(<Graph />, document.getElementById("root"));
    

    演示:https://codesandbox.io/s/react-konva-animating-line-demo-erufn

    【讨论】:

    • 太好了,谢谢@lavrton。作为额外的奖励,您还修复了我一直坚持的其他问题,即在 componentDidMount 中使用 setAttrs,我最初尝试直接设置属性,但它似乎不起作用。
    猜你喜欢
    • 2019-04-19
    • 2020-10-21
    • 2020-02-27
    • 2023-02-02
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多