【问题标题】:Canvas animation / reactjs / with requestAnimationFrame画布动画 / reactjs / 带有 requestAnimationFrame
【发布时间】:2019-05-08 17:52:00
【问题描述】:

我的应用程序上有多个画布动画,除this 外,一切正常,但现在我的动画框架有问题(我的怀疑)。

当我加载组件(动画 1)然后更改为组件(动画 2)然后返回到第一个组件时发生了一些奇怪的事情,每次我回到那个组件时动画都会变得更快,我不知道原因。 两个组件的动画是相同的,上下移动对象。

奇怪的是,在我的控制台上,即使在 6-7 次切换之后,移动速度也始终相同,但物体每次移动的速度越来越快...... 知道可能是什么问题吗?

这是一个动画,第二个和这个很相似:

    import React, { Component } from 'react';
let loadBall = [];
let canvas;
let c;
let counterX = 40;
let counterY = 30;
let y =  counterY ;
class Loading extends Component {
    constructor(props){
        super(props)
        this.state = {
            vy: 0,
            time:this.props.time
        }
        this.loadingLoop = this.loadingLoop.bind(this);
    }
    componentDidMount(){
        canvas = document.getElementById('ball');
        canvas.height = 150;
        canvas.width = window.innerHeight;
        c = canvas.getContext('2d');
        this.loadingInit()
        this.loadingLoop()
        window.addEventListener('resize', () => {
            canvas.width = window.innerHeight;
            this.loadingInit()
        })
        this.loadingInit();
    }
    loadingLoop(){
        requestAnimationFrame(this.loadingLoop);
        c.clearRect(0,0, canvas.width, canvas.height);
        for (let i = 0; i < loadBall.length; i++) {
            loadBall[i].update();
        }
    }
    loadingInit(){
        loadBall = [];
        for (let i = 0; i < 3; i++) {
            let radius = 30//Math.floor(Math.random() * 20) + 15;
            let x =  (canvas.width / 2) - (radius * 4) + counterX;
            y = counterY;
            let color = colors[i];
            loadBall.push(new loadingBall(x,y, radius, color));
            counterY += 30;
            counterX += 70;
        }
    }
render() {
    return (
        <canvas id='ball' style={{position:'fixed', top: '50%', left: '50%',WebkitTransform:'translate(-50%, -50%)'}}></canvas>
    );
}
}

function loadingBall(x,y,radius,color){
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;
    this.move = 2
    this.update = () =>{
        if (this.y + this.radius + this.move >= canvas.height - 3) {
            this.move = -this.move    
        } 
        if (this.y - this.radius - this.move <= 3) {
            this.move = 2;
        }
        this.y += this.move;
        this.draw();
    }
    this.draw = () => {
        c.beginPath();
        c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        c.fillRect(this.x, this.y, this.radius, 5);
        c.fillStyle = this.color;
        c.fill();
        c.strokeStyle = this.color;
        c.stroke();
        c.closePath();
    }
}
export default Loading;

任何建议都会有所帮助!

【问题讨论】:

  • 似乎没有任何东西会停止您的渲染周期(即当组件卸载时)。这可能会导致现有的渲染周期继续在后台运行(当组件卸载时),然后,当再次安装组件时,产生第二个渲染周期,导致两个渲染周期串联运行,这将解释什么似乎是在你的动画中“加速”
  • 我尝试使用componentWillUnmount并清除矩形,空数组,取消动画但似乎没有任何效果......卸载组件时如何停止动画??
  • 刚刚在下面添加了一个答案 - 希望对您有所帮助

标签: javascript reactjs canvas html5-canvas requestanimationframe


【解决方案1】:

这个问题很可能是由于卸载组件后渲染循环(即this.loadingLoop)没有停止造成的。结果,当组件被卸载时,渲染循环继续运行,当组件再次被安装时,一个新的渲染循环开始 - 这导致两个渲染循环串联运行,导致动画中感知的“加速”。

解决此问题的一种方法是向您的组件添加一个标志,以控制渲染循环的继续。这可以通过添加以下内容来实现:

constructor(props){
    super(props)
    this.state = {
        vy: 0,
        time:this.props.time
    }
    this.loadingLoop = this.loadingLoop.bind(this);

    // Add this flag to control if animation is allowed to continue
    this.stopAnimation = false;
}

componentDidMount(){

    // Add this to the start of componentDidMount to let animation 
    // start and continue while component is mounted
    this.stopAnimation = false;

    // ...
    // your existing code
    // ...
}

componentWillUnmount() {

    // When the component unmounts, set flag to stop animation
    this.stopAnimation = true;
}

loadingLoop(){

    // If the stopAnimation flag is not truthy, stop future
    // frames for this animation cycle
    if( this.stopAnimation ) {
       return
    }

    requestAnimationFrame(this.loadingLoop);

    c.clearRect(0,0, canvas.width, canvas.height);
    for (let i = 0; i < loadBall.length; i++) {
        loadBall[i].update();
    }
}

【讨论】:

  • 很高兴听到这个消息:)
猜你喜欢
  • 1970-01-01
  • 2015-11-03
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
  • 1970-01-01
  • 2015-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多