React中的SVG弧形路径动画



我正在使用React,我想要实现的是在SVG弧路径发生变化时在其上生成动画。基本上,我有一个量表,它显示0到100之间的某个值,这个值可以改变(在下面的例子中,它每秒都会改变(。

我创建了这个代码笔来模拟我想要的东西(下面的代码(:https://codepen.io/Gesma94/pen/oJvjwe

正如您在示例中看到的,我在SVG中使用d3创建了一个Gauge,其中蓝色条可能会占用或多或少的时间空间;正如您所看到的,当Gauge被重新渲染时,新的蓝色条只是被渲染,在"旧点"one_answers"新点"之间没有任何动画。

我想实现的是在酒吧之前的点和酒吧将要去的点之间有一个平稳的移动(希望我已经清楚了(。

class MyComponent extends React.Component {
render() {
console.log("Rendering");
const value = (this.props.value * Math.PI / 100) - Math.PI/2;
const currentValueFilledCircle = d3.arc()
.innerRadius(37.5)
.outerRadius(49.5)
.startAngle(-Math.PI/2)
.endAngle(value)(null);
const currentValueEmptyCircle = d3.arc()
.innerRadius(37.5)
.outerRadius(49.5)
.startAngle(value)
.endAngle(Math.PI/2)(null);
return (
<div style={{width: "300px", height: "300px"}}>
<svg height="100%" width="100%" viewBox="-50 -50 100 100">
<g>
<path d={currentValueFilledCircle} fill="blue" />
<path d={currentValueEmptyCircle} fill="gray" />
</g>
</svg>
</div>
);
};
}
class App extends React.Component {
constructor() {
super();
this.value = 77;
}
componentDidMount() {
this.interval = setInterval(() => {
const diff = Math.floor(Math.random() * 7) - 3;
let newCurrentValue = this.value + diff;
if (newCurrentValue > 100) newCurrentValue = 100;
else if (newCurrentValue < 0) newCurrentValue = 0;
this.value = newCurrentValue;
this.forceUpdate();
}, 500);
}
render() {
return (<MyComponent value={this.value} />)
}
}
ReactDOM.render(<App />, document.getElementById('app'));

所以,我挣扎了一段时间,但我找到了一个使用react-move/Animate的解决方案:https://react-move.js.org/#/documentation/animate

由于我无法在Codepen上工作,我在沙盒中重现了这种情况,它就在那里:https://codesandbox.io/embed/0qyrmyrw

要点是代码的以下部分:

<Animate
start={{ value: this.props.value }}
update={{
value: [this.props.value], // Before the sqaure brackets!!
timing: { duration: 750 }
}}
>
{(state: { value: number }) => {
const scaledValue = (state.value * Math.PI) / 100 - Math.PI / 2;
const currentValueFilledCircle = arc()
.innerRadius(37.5)
.outerRadius(49.5)
.startAngle(-Math.PI / 2)
.endAngle(scaledValue)(null);
const currentValueEmptyCircle = arc()
.innerRadius(37.5)
.outerRadius(49.5)
.startAngle(scaledValue)
.endAngle(Math.PI / 2)(null);
return (
<React.Fragment>
<path d={currentValueFilledCircle} fill="blue" />
<path d={currentValueEmptyCircle} fill="gray" />
</React.Fragment>
);
}}
</Animate>

基本上,通过编写update={{value: [this.props.value] ... }}Animate组件只需运行一组具有不同值的render((方法,从上一个值到当前值,因此它可以提供平滑的移动效果。

最新更新