admin管理员组文章数量:1026989
The issue can be seen in action here:
On first load, you'll see the blue circle going around and the red box fading out and in.
The circle is animated via svg tag and the box via css animations.
If you click anywhere on the canvas, the code triggers a re-render, which can be verified by opening the console.
My expectation would be for both animations to reset on click, however that does not happen.
I have a hunch that this has something to do with caching and react's shadow DOM.
Why's this happening? How to fix it?
The code is the following:
#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'));
Thank you.
The issue can be seen in action here:
https://codepen.io/fsabe/pen/opEVNR?editors=0110
On first load, you'll see the blue circle going around and the red box fading out and in.
The circle is animated via svg tag and the box via css animations.
If you click anywhere on the canvas, the code triggers a re-render, which can be verified by opening the console.
My expectation would be for both animations to reset on click, however that does not happen.
I have a hunch that this has something to do with caching and react's shadow DOM.
Why's this happening? How to fix it?
The code is the following:
#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'));
Thank you.
Share Improve this question edited Jan 10, 2018 at 1:51 fs_ asked Jan 10, 2018 at 1:39 fs_fs_ 1962 silver badges7 bronze badges1 Answer
Reset to default 6React is reusing the elements, therefore the animations won't replay b/c they've already played for the current elements.
I think it's easier to resort to dom operations in this situation, versus some setState
trickery.
https://codepen.io/guanzo/pen/vpdPzX?editors=0110
Store the refs to the 2 elements, then trigger the animations with 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'));
The issue can be seen in action here:
On first load, you'll see the blue circle going around and the red box fading out and in.
The circle is animated via svg tag and the box via css animations.
If you click anywhere on the canvas, the code triggers a re-render, which can be verified by opening the console.
My expectation would be for both animations to reset on click, however that does not happen.
I have a hunch that this has something to do with caching and react's shadow DOM.
Why's this happening? How to fix it?
The code is the following:
#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'));
Thank you.
The issue can be seen in action here:
https://codepen.io/fsabe/pen/opEVNR?editors=0110
On first load, you'll see the blue circle going around and the red box fading out and in.
The circle is animated via svg tag and the box via css animations.
If you click anywhere on the canvas, the code triggers a re-render, which can be verified by opening the console.
My expectation would be for both animations to reset on click, however that does not happen.
I have a hunch that this has something to do with caching and react's shadow DOM.
Why's this happening? How to fix it?
The code is the following:
#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'));
Thank you.
Share Improve this question edited Jan 10, 2018 at 1:51 fs_ asked Jan 10, 2018 at 1:39 fs_fs_ 1962 silver badges7 bronze badges1 Answer
Reset to default 6React is reusing the elements, therefore the animations won't replay b/c they've already played for the current elements.
I think it's easier to resort to dom operations in this situation, versus some setState
trickery.
https://codepen.io/guanzo/pen/vpdPzX?editors=0110
Store the refs to the 2 elements, then trigger the animations with 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'));
本文标签: javascriptReactJSCSS and SVG animationsand rerenderingStack Overflow
版权声明:本文标题:javascript - ReactJS, CSS and SVG animations, and re-rendering - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745168101a2137915.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论