Canvas 动画/reactjs/与requestAnimationFrame
Canvas animation / reactjs / with requestAnimationFrame
我的应用程序中有多个 canvas 动画,除 this 外一切正常,但现在我的动画帧出现问题(我怀疑)。
当我加载组件 (animation1) 然后更改为组件 (animation 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;
任何建议都会有帮助!
这个问题很可能是由于您的渲染循环(即 this.loadingLoop
)在您的组件卸载后没有停止。结果,当组件被卸载时,渲染循环继续 运行 并且当组件再次被安装时,一个新的渲染循环开始 - 这导致两个渲染循环 运行 串联,导致动画中的感知"speed up"。
解决此问题的一种方法是向您的组件添加一个标志来控制渲染循环的继续。这可以通过添加以下内容来实现:
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();
}
}
我的应用程序中有多个 canvas 动画,除 this 外一切正常,但现在我的动画帧出现问题(我怀疑)。
当我加载组件 (animation1) 然后更改为组件 (animation 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;
任何建议都会有帮助!
这个问题很可能是由于您的渲染循环(即 this.loadingLoop
)在您的组件卸载后没有停止。结果,当组件被卸载时,渲染循环继续 运行 并且当组件再次被安装时,一个新的渲染循环开始 - 这导致两个渲染循环 运行 串联,导致动画中的感知"speed up"。
解决此问题的一种方法是向您的组件添加一个标志来控制渲染循环的继续。这可以通过添加以下内容来实现:
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();
}
}