javascript - ReactJS、CSS 和 SVG 动画,以及重新渲染

标签 javascript css reactjs svg

这个问题可以在这里看到:
https://codepen.io/fsabe/pen/opEVNR?editors=0110

在第一次加载时,您会看到蓝色圆圈环绕,红色框逐渐淡入。
圆圈通过 svg 标签动画,方框通过 css 动画。
如果您点击 Canvas 上的任意位置,代码会触发重新渲染,可以通过打开控制台进行验证。

我的期望是两个动画都在点击时重置,但是这并没有发生。
我有一种预感,这与缓存和 React 的影子 DOM 有关。

为什么会这样?如何解决?

代码如下:

#nonSvgBox {
  animation-duration: 1s;
  animation-name: fade;
  width: 100px;
  height: 100px;
  background-color: red;
}

@keyframes fade {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
class Component extends React.Component {
  onClick() {
    this.setState({a: 1});
  }

  render() {
    console.log('rendering');
    return (
      <div onClick={() => this.onClick()}>
        <svg>
          <path 
            stroke="blue"
            strokeWidth="10"
            fill="transparent"
            d="M50 10 a 40 40 0 0 1 0 80 a 40 40 0 0 1 0 -80"
            strokeDasharray="251.2,251.2">
            <animate
              attributeType="css"
              attributeName="stroke-dasharray"
              from="0" to="251.2" dur="1s" />
          </path>
        </svg>
        <div id="nonSvgBox"></div>
      </div>
    );
  }
}

ReactDOM.render(<Component />, document.getElementById('app'));

谢谢。

最佳答案

React 正在重用元素,因此动画不会重播 b/c 它们已经为当前元素播放过。

我认为在这种情况下求助于 dom 操作比一些 setState 技巧更容易。

https://codepen.io/guanzo/pen/vpdPzX?editors=0110

将 refs 存储到 2 个元素,然后用 JS 触发动画。

class Component extends React.Component {
  onClick() {
    this.svgAnimate.beginElement()//triggers animation
    this.square.style.animation = 'none';//override css animation
    this.square.offsetHeight; /* trigger reflow */
    this.square.style.animation = null; //fallback to css animation
  }

    render() {
    console.log('rendering');
        return (
            <div onClick={() => this.onClick()}>
                <svg>
                    <path 
                        stroke="blue"
            strokeWidth="10"
                        fill="transparent"
                        d="M50 10 a 40 40 0 0 1 0 80 a 40 40 0 0 1 0 -80"
            strokeDasharray="251.2,251.2">
              <animate
                ref={(svgAnimate) => { this.svgAnimate = svgAnimate; }} 
                attributeType="css"
                attributeName="stroke-dasharray"
                from="0" to="251.2" dur="1s" />
                </path>
              </svg>
        <div id="nonSvgBox"
          ref={(square) => { this.square = square; }} 
          ></div>
            </div>
        );
    }
}

ReactDOM.render(<Component />, document.getElementById('app'));

关于javascript - ReactJS、CSS 和 SVG 动画,以及重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48179124/

相关文章:

javascript - 滚动长度如何根据网页长度的增加而变化

reactjs - 引用错误 : $RefreshReg$ is not defined

javascript - 在 'style' 和 'onclick' 等属性中编写注释的正确方法是什么?

ios - 修复了在 iOS 11 的 webview 中向下滚动时标题消失的问题

javascript - 默认情况下/在页面上时保持按下按钮

javascript - Try-catch 对于 JS 中的 400 错误不起作用

javascript - React.js 直接用 HTML 写组件

javascript - 获取当前在 Google Map API V3 上的叠加形状列表

javascript - 非点击目标时子菜单不隐藏

javascript - 为什么 Chrome 开发工具说变量未定义?