javascript - 如何在 Class 对象中使用 requestAnimationFrame

标签 javascript oop animation scope requestanimationframe

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

我正在使用 step功能和requestAnimationFrame课外:

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);
}

我可以把它变成一种方法,替换 circleLinethis .第一次运行时效果很好,但是当它调用 this.step回调第二次,好吧,我们处于回调黑洞和对 this 的引用被打破。做旧self = this一旦我们跳入回调 this 也不会工作未定义(我不确定为什么)。这是一种方法:
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);
  }
}

关于如何将“布线”保持在对象内部的任何想法?

这是或多或少适用于 step 的代码类外定义的函数。
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;
}

然后单击一个按钮...
function runProgram() {
  window.requestAnimationFrame(step);
}

最佳答案

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

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

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

如果你有一个局部范围的变量设置为 this.step.bind(this)您可以通过它并避免不断重新绑定(bind)。

另一种选择是:
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 伪递归调用的纯本地范围函数中执行动画。 .

注意:如果您无意中调用了同时启动动画的另一个函数,则任一版本的代码都会产生不良交互。

关于javascript - 如何在 Class 对象中使用 requestAnimationFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48816441/

相关文章:

javascript - TypeScript Array<T>.splice 覆盖

objective-c - 子类化 Objective C 类方法

c# - 如何限定 C# View 模型的范围

jQuery 显示/隐藏回调动画(不想要它)

javascript - 如何通过将鼠标悬停在另一个元素上来更改一个元素?

缩小时出现 Javascript 错误

javascript - 当对象可能是字符串时使用 'in'

javascript - 使输入宽度相同

javascript - OOP 方法中是否可以知道 ajax 调用何时完成

ios - 通过 AVExportSession 导出带有隐式动画的 CALayer