ReactJS、CSS 和 SVG 动画,以及重新渲染
ReactJS, CSS and SVG animations, and re-rendering
可以在此处查看此问题:
https://codepen.io/fsabe/pen/opEVNR?editors=0110
首次加载时,您会看到蓝色圆圈环绕,红色框逐渐淡入。
圆圈通过 svg 标签动画,方框通过 css 动画。
如果单击 canvas 上的任意位置,代码会触发重新渲染,可通过打开控制台进行验证。
我的期望是两个动画都在点击时重置,但是这并没有发生。
我有一种预感,这与缓存和反应的影子有关 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
存储2个元素的refs,然后用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'));
可以在此处查看此问题:
https://codepen.io/fsabe/pen/opEVNR?editors=0110
首次加载时,您会看到蓝色圆圈环绕,红色框逐渐淡入。
圆圈通过 svg 标签动画,方框通过 css 动画。
如果单击 canvas 上的任意位置,代码会触发重新渲染,可通过打开控制台进行验证。
我的期望是两个动画都在点击时重置,但是这并没有发生。
我有一种预感,这与缓存和反应的影子有关 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
存储2个元素的refs,然后用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'));