为什么每次删除和重新创建目标元素时动画速度都会增加
Why is animation speed increasing each time the target element is deleted and recreated?
我基于别人的Chrome实验创建了一个jQuery插件,它将画布元素插入到你的目标元素中,并在画布中绘制一个交互式星形字段。
每次调整窗口大小时,画布元素都会被移除,然后恢复,以便其大小与其父元素匹配,并且所有内容都会正确地设置动画;它反应灵敏。
但是,无论何时恢复,动画的速度都会增加。它为什么要这样做?我以为所有的变量(包括速度)都用这个.start()方法重置为默认值。
您可以在CodePen上看到代码(和演示);你也可以在Github上分叉,尽管我认为Github版本比我自己的版本晚了几次提交。
(此外,这是我的第一个真正的jQuery插件,所以如果你看到任何问题,请告诉我。)
有线索吗?
单独使用cancelAnimationFrame
不需要停止动画循环(事实证明)。
为了绝对确定,您还需要使用条件检查-一个通用示例:
var isPlaying; /// our condition
function loop() {
/* funky stuff here */
If (isPlaying === true)
requestId = requestAnimationFrame(loop);
}
然后启动:
functiom start() {
isPlaying = true;
loop();
}
现在,当你想停止动画你需要做:
function stop() {
isPlaying = false;
/// kill any request in progress
if (requestId) cancelAnimationFrame(requestId);
}
如果你不这样做,你就有把调用堆叠到循环中的风险——例如:
如果您调整大小,并且cAF没有阻止rAF重新触发循环,则旧循环仍将在后台运行,您将在此基础上启动一个新循环。
这就是为什么你会看到速度的增加,因为新旧循环都会在恒星被绘制到屏幕之前增加位置。
在第三次重新调整大小时,又开始了另一个循环,最终整个过程将阻塞浏览器。
然而
与其使用循环的启动和停止,我建议您采用以下方法:
- 创建一次画布
- 循环只启动一次
- 在这种情况下,对整个重新调整大小机制进行重新分解可能是有益的(例如,将所需的初始化(元素的宽度和高度)与以后可以重新使用的第一次初始化分开)
- 没有必要为每个重新大小重新初始化星形,因为您将使用宽度和高度来检查它们的边界(画布将进行剪裁)
调整大小时,可以考虑使用条件标志来防止在重新调整大小时渲染。
尽管通常情况下,由于JavaScript的单线程特性,在画布更改大小时阻止渲染的条件实际上是不必要的,在这种情况下,您可以对当前元素大小进行边界检查。画布本身会为您处理剪裁。
话虽如此:不应该每次都重新创建画布元素。
这会产生不必要的开销。如果画布已经创建,只需在其属性上设置新的宽度和高度:
if (typeof canvas === 'undefined')
canvas = /* only create if it doesn't exist */
canvas.width = width;
canvas.height = height;
PS:I";"受阻";带有上面的一些暴力实现的版本。它远未完成或质量不高,但为了举例说明,它消除了一些痛苦,给你一些建议。
请根据您的需要领养。
更新:
要包含更多来自附加评论的信息:
当在画布元素上设置新大小时,其上下文将重置为默认值(fillStyle
变为透明,strokeStyle
变为黑色,转换重置,依此类推)。
这意味着在设置每个新大小后,必须重新设置所有非默认设置。
设置新的大小也可以(通常也可以)清除画布的内容,使所有像素都变成透明的黑色。
对于手动更新canvas
元素维度的用户:
调整canvas
元素的大小会导致它丢弃任何绘制到调整大小点的内容。
这个脚本的动画应该在调整大小后继续绘制到画布上,但唯一会更新的是背景的fillRect
;星星消失了。
在更改canvas
元素的维度后,唯一能让恒星返回的方法是:额外调用context.strokeStyle
。我不知道为什么;如果有人能澄清这件事,我将不胜感激。
编辑: 根据下面的注释,画布中的所有都会重置,包括笔划和填充样式(显然都默认为黑色)。因此,当调整大小时,我不得不重新定义笔划和填充样式。
- 如何覆盖锚点元素's href目标,并在我点击转到目标javascript时删除其他错误
- 任何一种简单的方法都可以将带有onload的元素作为目标
- AngularJs的ng-click$事件将子元素作为目标传递
- 从定位目标中的元素中清除类
- 查找元素的目标
- 指定数组中的元素对,其总和等于特定的目标数字
- 内容以其开头的目标元素
- 在 Jquery 中获取目标元素的属性
- 给定一个带有数字的数组,我如何编写一个递归函数,当 2 个元素加起来为一个目标时,它会在数组中查找索引
- 使用 jQuery 从目标页面而不是当前页面获取元素文本
- AngularJS:如何防止ng-click以子元素为目标
- 有人能向我解释一下:将元素附加到目标与将元素分配到目标
- window.onerror获取元素目标
- 使用next()的jQuery目标元素不起作用
- 以elementsByClassName数组的任何元素为目标
- ReactJS-目标随机元素
- 基于比较子元素内容和目标标题内容的Javascript排序元素
- Ember.js:在模板中呈现谷歌图表(仅当存在时才称为目标DOM元素)
- 在 HTA 中将元素目标发送到 iframe
- 事件委派 - 父元素目标而不是子元素