【问题标题】:I am trying to animate an object with css in react and change the animation (timing) dynamically, how can I set the style after animation end?我正在尝试使用 css 为对象设置动画并动态更改动画(计时),如何在动画结束后设置样式?
【发布时间】:2021-11-06 13:14:23
【问题描述】:

我正在尝试制作一个漂浮的热气球风格按钮(在 x 和 y 空间上平移)。目前我正在使用 CSS 变量来设置动画属性,但我只能这样做一次,否则我会收到一条错误消息
“TypeError:无法分配给对象'#'的只读属性'--animation-time'”
我如何解决这个问题,以便能够为动画开始、结束和持续多长时间设置新的随机属性? 目前我有这个:

class HotAir extends React.Component{
  constructor(props){  
    super(props);  
    this.state = {
      link: props.link,
      cls: props.cls,
      img: props.img,
      text: props.text,
    }  
  }  

  render(){
    var cssProperties = {};
    cssProperties['--animation-time'] = Math.random()*10 + 's';
    console.log(cssProperties);

    
    return(
      <div className="balloon" style={cssProperties} onAnimationEnd={()=> cssProperties['--animation-time'] = '60s'}>
        <Link to={this.state.link}><button className="balloonbutt">
          <img src={this.state.img} alt=""></img>
          <div className="balloontext">{this.state.text}</div></button>
        </Link>
      </div>
    );
  }
}

这是我的相关css

.balloon{
    --animation-time: 60s;
    --x-float-start: 10vw;
    --y-float-start: 10vh;
    --x-float-end: 20vw;
    --y-float-end: 20vh;
    position: relative;
  text-align: center;
  color: white;
    animation: float var(--animation-time) linear;
}
@keyframes float{
    0%{
        left: var(--x-float-start);
        top: var(--y-float-start);
    }
    100%{
        left: var(--x-float-end);
        top: var(--y-float-end);
    }
}

【问题讨论】:

  • 我试过你的代码,在stackblitz.com/edit/react-ts-pemaug上没有问题
  • 一个建议,不要使用 var。改用 const 或 let 。我认为这一定与您的代码 linting 设置有关。
  • @SanishJoseph 是的,当我在动画完成后尝试再次设置时会出现问题
  • 我认为您应该将变量移动到状态对象并按照我的回答进行处理。如果您仍然遇到错误,请告诉我。

标签: javascript css reactjs animation


【解决方案1】:

我以更 Reacty 的方式修改了您的代码。您正在使用 var 对象并改变数据,这不是 React 期望的事情。我已经更新了我的代码,希望你的 linting 工具在更改后不会抱怨。

变化:

  1. 已添加 cssProperties 声明,因此 react 将知道该属性。
  2. 不是在动画结束时改变值,而是更新状态,

this.setState({ ...这个状态, cssProperties: { '--animation-time': '60' } });

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';

interface AppProps {}
interface AppState {
  name: string;
  cssProperties;
}

class App extends Component<AppProps, AppState> {
  constructor(props) {
    super(props);
    this.state = {
      name: 'React',
      cssProperties: {
    '--animation-time': Math.random() * 10 + 's',
    '--x-float-start': Math.trunc(Math.random() * 200) - 10 + 'px',
    '--y-float-start': Math.trunc(Math.random() * 200) - 10 + 'px',
    '--x-float-end': Math.trunc(Math.random() * 200) - 10 + 'px',
    '--y-float-end': Math.trunc(Math.random() * 200) - 10 + 'px'
  }
    };
  }

  render() {
    console.log(this.state.cssProperties);
    return (
      <div
        className="balloon"
        style={this.state.cssProperties}
        onAnimationIteration={() => {
          console.log(this.state.cssProperties);
      this.setState({
        ...this.state,
        cssProperties: {
          ...this.state.cssProperties,
          '--x-float-start': this.state.cssProperties['--x-float-end'],
          '--y-float-start': this.state.cssProperties['--y-float-end'],
          '--x-float-end': Math.trunc(Math.random() * 200) - 10 + 'px',
          '--y-float-end': Math.trunc(Math.random() * 200) - 10 + 'px'
        }
      });
          
        }}
      >
        <Hello name={this.state.name} />
        <p>Start editing to see some magic happen :)</p>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

更新

由于您需要无限动画,因此您的 CSS 应该具有该选项。

 animation: float var(--animation-time) linear infinite;

【讨论】:

  • 这行得通!谢谢!但是现在它在从 onAnimationEnd 方法设置动画后停止动画。有什么办法可以反复调用吗?理想情况下,它会在每个动画之后无限选择一个新位置?
  • 您的意思是每次动画结束后都需要一个新值?保留你的随机值生成器而不是固定 60 可能。
  • 是的,我刚刚在我的示例中使用了 60 来查看是否可以设置它。我已将 onAnimationEnd 函数更改为以下 this.setState({ ...this.state, cssProperties: { '--animation-time': '10s', '--x-float-start': this.state.cssProperties['--x-float-end'], '--y-float-start': this.state.cssProperties['--y-float-end'], '--x-float-end': Math.trunc(Math.random()*200) - 10 + 'px', '--y-float-end': Math.trunc(Math.random()*200) - 10 + 'px'} }); } 但我现在的问题是它只动画两次
  • 检查我的更新。在这种情况下,你需要有一个无限的动画。
  • 现在 onAnimationEnd 函数不会运行,因为动画是无限的/永远不会结束。需要明确的是,我希望它在每次动画结束时更改目的地,然后开始前往新的目的地。
猜你喜欢
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多