如何在 Class 对象中使用 requestAnimationFrame
How to use requestAnimationFrame inside a Class object
我有一个 class 需要一些坐标和持续时间数据。我想用它来制作 svg
的动画。更明确地说,我想使用该数据在一段时间内更改 svg
属性。
我在 class:
之外使用 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);
}
我可以把它变成一个方法,用this
代替circleLine
。这对于第一个 运行 通过来说工作正常,但是当它第二次调用 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);
}
}
关于如何将 "wiring" 保留在对象中的任何想法?
这是或多或少与 class 外部定义的 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 );
}
}
这也将被插入到 Class 中,目前它只是一个辅助函数:
function distancePerFrame(totalFrames, startEndPoints) {
return totalFrames > 0 ? Math.floor(Math.abs(startEndPoints[0] - startEndPoints[1]) / totalFrames) : 0;
}
然后单击一个按钮...
function runProgram() {
window.requestAnimationFrame(step);
}
您需要将 requestAnimationFrame
回调函数绑定到上下文。规范的做法是这样的:
window.requestAnimationFrame(this.step.bind(this))
但这并不理想,因为您要反复调用 .bind
并一遍又一遍地创建新函数引用,每帧一次。
如果您将局部范围的变量设置为 this.step.bind(this)
,您可以传递它并避免持续重新绑定。
另一种选择是:
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
.
称为 pseudo-recursively 的纯局部作用域函数中执行动画
注意:如果您无意中调用了另一个同时启动动画的函数,那么任何一个版本的代码都会出现严重的交互问题。
我有一个 class 需要一些坐标和持续时间数据。我想用它来制作 svg
的动画。更明确地说,我想使用该数据在一段时间内更改 svg
属性。
我在 class:
之外使用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);
}
我可以把它变成一个方法,用this
代替circleLine
。这对于第一个 运行 通过来说工作正常,但是当它第二次调用 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);
}
}
关于如何将 "wiring" 保留在对象中的任何想法?
这是或多或少与 class 外部定义的 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 );
}
}
这也将被插入到 Class 中,目前它只是一个辅助函数:
function distancePerFrame(totalFrames, startEndPoints) {
return totalFrames > 0 ? Math.floor(Math.abs(startEndPoints[0] - startEndPoints[1]) / totalFrames) : 0;
}
然后单击一个按钮...
function runProgram() {
window.requestAnimationFrame(step);
}
您需要将 requestAnimationFrame
回调函数绑定到上下文。规范的做法是这样的:
window.requestAnimationFrame(this.step.bind(this))
但这并不理想,因为您要反复调用 .bind
并一遍又一遍地创建新函数引用,每帧一次。
如果您将局部范围的变量设置为 this.step.bind(this)
,您可以传递它并避免持续重新绑定。
另一种选择是:
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
.
注意:如果您无意中调用了另一个同时启动动画的函数,那么任何一个版本的代码都会出现严重的交互问题。