我有一个温度计svg,我希望与它进行某种互动。交互将按照用户提供的值移动针。可以从游侠提供该值,并且应该通过移动针来更新温度计。
我在webpack bin中创建了一个示例,因此您可以在此处查看演示https://www.webpackbin.com/bins/-Khv7qwzOc5OlYE9UY-1
这就是我所做的
componentDidMount(){
this.animationH.setAttribute('from', this.animationH.getAttribute('to'));
this.animationH.setAttribute('to', this.state.value);
this.animationY.setAttribute('from', this.animationY.getAttribute('to'));
this.animationY.setAttribute('to', this.state.value);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
render() {
const {value} = this.state;
return (
<div>
<input
type="range"
min="1"
max="100"
step="1"
onChange={(event) => this.handleChange(event)}
/>
{value ? value : ''}
<svg width="133px" height="350px" viewBox="0 0 133 1113" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect id="Rectangle-2" stroke="#979797" strokeWidth="2.132" fill="#C20C0C" filter="url(#filter-1)" x="56.8899994" y="735" width="18" height="200">
<animate
attributeName="height"
from="0"
to="200"
fill="freeze"
dur="2s"
ref={(animationH) => this.animationH = animationH}
/>
<animate
attributeName="y"
from="935"
to="735"
fill="freeze"
dur="2s"
ref={(animationY) => this.animationY = animationY}
/>
</rect>
</svg>
</div>
);
}
答案 0 :(得分:0)
它没有更新,因为您通过动画设置height
和y
的{{1}}和<rect>
值,这些动画在componentWillMount
中触发。您有两种方法可以解决这个问题:
将componentWillMount
中的代码解压缩到新方法animate
,并在更改值时调用它:
// In your component
componentWillMount() {
this.animate();
}
animate() {
this.animationH.setAttribute('from', this.animationH.getAttribute('to'));
this.animationH.setAttribute('to', this.state.value);
this.animationY.setAttribute('from', this.animationY.getAttribute('to'));
this.animationY.setAttribute('to', this.state.value);
}
handleChange(event) {
this.setState({ value: event.target.value }, this.animate.bind(this));
// 2nd argument is a callback, called after setState is complete (it is potentially async)
}
不要使用SVG动画,只需使用state中的值将属性设置为render
- 方法中的rect,并将CSS转换应用于height
和{{1 }}。然后,您将在y
之后自动呈现正确的值。
工作示例:https://www.webpackbin.com/bins/-Ki4KIR0eSLQrGh2JrAz
setState
// In your component
render() {
return (
...
<rect
className="temperature-bar"
stroke="#979797"
strokeWidth="2.132"
fill="#C20C0C"
filter="url(#filter-1)"
x="56.8899994"
y={value}
width="18"
height={value}>
...
);
}
我会尽可能地建议第二种方法,因为它遵循React背后的核心思想:总是基于状态/道具进行渲染(而不是像触发动画时那样在渲染方法之外改变DOM)。 / p>
PS:你需要为rect正确计算// CSS for your component
rect.temperature-bar {
transition-property: y, height;
transition-duration: 2s;
transition-timing-function: linear;
}
和y
,因为现在结果完全错了,但你可能知道了。