如何在Class对象中使用requestAnimationFrame [英] How to use requestAnimationFrame inside a Class object

查看:203
本文介绍了如何在Class对象中使用requestAnimationFrame的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要一些坐标和持续时间数据的类。我想用它来制作 svg 的动画。更明确地说,我想使用该数据在一定时间内更改 svg 属性。

I have a class that takes some coordinate and duration data. I want to use it to animate an svg. In more explicit terms, I want to use that data to change svg attributes over a time frame.

m在类外使用 step 函数和 requestAnimationFrame

I'm using a step function and requestAnimationFrame outside the class:

function step(timestamp) {
  if (!start) start = timestamp
  var progress =  timestamp - start;
  var currentX = parseInt(document.querySelector('#start').getAttribute('cx'));
  var moveX =  distancePerFrame(circleMove.totalFrames(), circleMove.xLine);

  document.querySelector('#start').setAttribute('cx', currentX + moveX);
  if (progress < circleMove.duration) {
    window.requestAnimationFrame(step);
  }
}

var circleMove = new SingleLineAnimation(3000, startXY, endXY)

var start = null

function runProgram() {
  window.requestAnimationFrame(step);
}

我可以用它代替一个 circleLine this 。第一次运行就可以正常工作,但是当它第二次调用 this.step 回调时,很好,我们处于回调黑洞中,并且引用已损坏。一旦我们进入回调 this 是未定义的,那么做旧的 self = this 也不起作用。我不确定为什么)。这是一种方法:

I can make it a method, replacing the circleLine with this. That works fine for the first run through, but when it calls the this.step callback a second time, well, we're in a callback black hole and the reference to this is broken. Doing the old self = this won't work either, once we jump into the callback this is undefined(I'm not sure why). Here it is as a method:

step(timestamp) {
  var self = this;

  if (!start) start = timestamp
  var progress =  timestamp - start;
  var currentX = parseInt(document.querySelector('#start').getAttribute('cx'));
  var moveX =  distancePerFrame(self.totalFrames(), self.xLine);

  document.querySelector('#start').setAttribute('cx', currentX + moveX);
  if (progress < self.duration) {
    window.requestAnimationFrame(self.step);
  }
}

关于如何保留布线的任何想法

Any ideas on how to keep the "wiring" inside the Object?

这是在类外定义的 step 函数或多或少可以使用的代码。

Here's the code that more or less works with the step function defined outside the class.

class SingleLineAnimation { 
  constructor(duration, startXY, endXY) {
    this.duration = duration;
    this.xLine = [ startXY[0], endXY[0] ];
    this.yLine = [ startXY[1], endXY[1] ];
  }

  totalFrames(framerate = 60) { // Default to 60htz ie, 60 frames per second
    return Math.floor(this.duration * framerate / 1000);
  } 

  frame(progress) {
    return this.totalFrames() - Math.floor((this.duration - progress) / 17 );
  } 
}

现在这也将插入到类中

function distancePerFrame(totalFrames, startEndPoints) {
  return totalFrames > 0 ? Math.floor(Math.abs(startEndPoints[0] - startEndPoints[1]) / totalFrames) : 0;
}

然后单击按钮以...

And click a button to...

function runProgram() {
  window.requestAnimationFrame(step);
}


推荐答案

您需要绑定 requestAnimationFrame 回调函数到上下文。这样做的规范方法是这样的:

You need to bind the requestAnimationFrame callback function to a context. The canonical way of doing this is like this:

window.requestAnimationFrame(this.step.bind(this))

但这并不理想,因为您反复调用 .bind 并一遍又一遍地创建新的函数引用,每帧一次。

but it's not ideal because you're repeatedly calling .bind and creating a new function reference over and over, once per frame.

如果您将局部范围内的变量设置为 this.step.bind (this),您可以通过该操作并避免这种连续性的重新绑定。

If you had a locally scoped variable set to this.step.bind(this) you could pass that and avoid that continual rebinding.

另一种方法是:

function animate() {

    var start = performance.now();
    el = document.querySelector('#start');

    // use var self = this if you need to refer to `this` inside `frame()`

    function frame(timestamp) {

        var progress =  timestamp - start;
        var currentX = parseInt(el.getAttribute('cx'));
        var moveX =  distancePerFrame(circleMove.totalFrames(), circleMove.xLine);
        el.setAttribute('cx', currentX + moveX);

        if (progress < circleMove.duration) {
            window.requestAnimationFrame(frame);
        }
    }

    window.requestAnimationFrame(frame);
}

即您要设置初始状态,然后在一个纯本地范围内的函数中进行动画处理,该函数由 requestAnimationFrame 进行伪递归调用。

i.e. you're setting up the initial state, and then doing the animation within a purely locally scoped function that's called pseudo-recursively by requestAnimationFrame.

NB:如果您无意中调用了同时启动动画的另一个函数,则这两个代码版本之间的交互都会很糟糕。

NB: either version of the code will interact badly if you inadvertently call another function that initiates an animation at the same time.

这篇关于如何在Class对象中使用requestAnimationFrame的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆