简体   繁体   English

检测canvas / css3动画在不可见时和视口外是否正在优化

[英]Detect if canvas/css3 animations are being optimized when not visible and outside viewport

I'm assuming with all these hardware accelerated animations in HTML5 that animations that are running outside the viewport are not actually rendered. 我假设在HTML5中使用所有这些硬件加速动画,实际上不会渲染在视口外运行的动画。 I want to be able to detect if that is happening. 我希望能够发现是否发生了这种情况。

I've tried using webkitCSSMatrix in a loop on an object that moves up and down 100px every second to try and determine how many pixels it was moving each tick but there's no difference if I move the animation out of view. 我已经尝试在一个循环中循环使用webkitCSSMatrix ,该对象每秒上下移动100px以尝试确定每个刻度移动的像素数,但如果我将动画移出视图则没有区别。

Any ideas? 有任何想法吗?

You can use an individual timer test to see difference in objects being drawn outside versus inside for the pseudo-empirical side (timers doesn't actually prove anything but gives you a strong indisium ). 您可以使用单独的计时器测试来查看伪经验方面在外部和内部绘制的对象的差异(计时器实际上不会证明任何东西,但会给您带来强烈的冲突 )。

However, knowing how the canvas work can give you a solid pointer too. 但是,了解画布的工作方式也可以为您提供可靠的指针。 For example, a canvas is a simple bitmap without any internal management (beyond screen refresh). 例如,画布是一个简单的位图,没有任何内部管理(超出屏幕刷新)。 That means you cannot possibly actually write anything outside its bound as this would corrupt memory. 这意味着你不可能实际写出超出其范围的任何东西,因为这会破坏内存。 In other words, clipping do take place for this very basic reason. 换句话说,剪切确实是出于这个非常基本的原因。

For the timer tests you can run a simple test where you draw something within the bounds and then the same offset to outside the bounds: 对于计时器测试,您可以运行一个简单的测试,在边界内绘制一些东西,然后在边界外绘制相同的偏移量:

Update: It seems as I misunderstood the question to be outside the canvas bitmap and not outside viewport in general. 更新:似乎我误解了问题是在画布位图之外,而不是在视口之外。

So a small update in regards to outside viewport regardless if that is canvas or not - 所以关于外部视口的小更新,无论是否是画布 -

It's a bit more complicated to describe browser updates than just a canvas but in principle: Everything that is not visible on a screen is clipped (not drawn). 描述浏览器更新比仅使用画布更复杂但原则上:屏幕上看不到的所有内容都被剪裁(未绘制)。 Seems perhaps obvious and it sort of it, but that doesn't mean there isn't any updates going on elsewhere. 看起来似乎很明显而且有点类似,但这并不意味着其他地方没有任何更新。

Browser may or may not keep an internal bitmap of the elements that are to be drawn to the screen (clipped if partly in view or not at all if outside view). 浏览器可能会也可能不会保留要绘制到屏幕的元素的内部位图(如果部分在视图中则剪裁,如果在外部视图则不剪辑)。

The main difference is that the browser may (dependent on implementation) update this internal bitmap if there is a need to, even if it won't be visible, ie. 主要区别在于,如果需要,浏览器可以 (取决于实现)更新该内部位图,即使它不可见,即。 DOM re-flow that is affected by this element's position, dimension and stack position. 受此元素位置,维度和堆栈位置影响的DOM重新流动。

For that reason you may see performance hit in some browsers. 因此,您可能会在某些浏览器中看到性能受损。 The browser can also choose to only update the bitmap content when visible and only adjust sizes when it is not. 浏览器还可以选择仅在可见时更新位图内容 ,并且仅在不显示时调整大小。

Unfortunately there is no accurate way to measure if this happens as it is dependent on many factors (fixed/absolute elements versus non-fixed/absolute, what content, browser implementation, hardware accelerated or not and so forth). 遗憾的是,没有准确的方法来衡量是否会发生这种情况,因为它取决于许多因素(固定/绝对元素与非固定/绝对元素,内容,浏览器实现,硬件加速与否等等)。

The canvas element is naiv so it is simple to predict, but if you draw something to canvas while canvas is outside viewport it will be drawn to its bitmap and shown when canvas is in view again. 画布元素是天真的,所以它很容易预测,但是如果画布在画面之外的时候绘制了一些东西,它将被绘制到它的位图并在画布再次显示时显示。 However, try to do a window resize and the content of the canvas will disappear (in some browsers) and you will need to redraw. 但是,尝试进行窗口大小调整,画布的内容将消失(在某些浏览器中),您需要重绘。 This means there is at least one layer less involved in the process with canvas than with other elements. 这意味着在使用画布的过程中至少有一个层比其他元素更少。

I hope that made any sense - my apologies, I was a bit unprepared to do this explanation as I just realized I misunderstood the question. 我希望这有任何意义 - 我道歉,我有点没准备做这个解释,因为我刚才意识到我误解了这个问题。

End of update 更新结束

Here is a simple online test 这是一个简单的在线测试

In this test we draw 10,000 filled rectangles, at one button inside, at the other button inside. 在这个测试中,我们在内部的一个按钮处,在内部的另一个按钮处绘制10,000个填充的矩形。 It's not a scientific accurate test, but it shows clearly a difference as when drawing is outside everything it does is to check bound and doesn't update anything in the bitmap's array - 这不是一个科学的准确测试,但它清楚地显示了一个区别,因为当绘图超出它所做的一切时,它检查绑定并且不会更新位图数组中的任何内容 -

function draw(x) {

    console.time('timer');
    var cnt = 10000, w = ez.width, h = ez.height;

    while(cnt--) {
        ctx.fillRect(x, 0, w, h);
    }

    console.timeEnd('timer');
}

inside.addEventListener('click', function(){draw(0)}, false);
outside.addEventListener('click', function(){draw(ez.width)}, false);

The result of this on my snail computer using the console timer and Chrome is: 使用控制台计时器和Chrome在我的蜗牛计算机上的结果是:

timer: 3156.000ms 计时器:3156.000ms
timer: 112.000ms 计时器:112.000ms

That is a ratio of (inside:outside) 3156:112 - or - it took 28x longer when actually drawing something. 这是(内部:外部)3156:112的比例 - 或 - 实际绘制某物时花费了28倍。 This indicate that the browser only spend time to check the bounds but doesn't actually move any data in memory if outside bound. 这表明浏览器只花时间检查边界,但实际上并没有在内存中移动任何数据。

The other method is similar to what is already answered, to use the built in tools. 另一种方法类似于已经回答的方法,使用内置工具。 But for this use the profiler instead: 但是为此使用了分析器

Go go the console and select profiles and CPU profile: 转到控制台并选择配置文件和CPU配置文件:

在此输入图像描述

  • Start to record one profile and then hit Inside button. 开始录制一个配置文件,然后点击内部按钮。 Stop when done 完成后停止
  • Start to record a second profile and then hit Outside button. 开始录制第二个配置文件,然后点击“外部”按钮。 Stop when done 完成后停止

Now you can compare the two profiles - for inside drawing I got this result: 现在你可以比较两个配置文件 - 对于内部绘图我得到了这个结果:

在此输入图像描述

Here you see it uses about 9.92% to draw the filled rectangles (not adjusted for idle time). 在这里,您可以看到它使用大约9.92%来绘制填充的矩形(未调整空闲时间)。

In the second profile I got this: 在第二个配置文件中我得到了这个:

在此输入图像描述

Here only 1.24% was used to "draw". 这里只有1.24%用于“抽奖”。

Ratio here is 9.92:1.24 or 8 times. 这里的比例是9.92:1.24或8倍。 In both cases you can see there a huge differences in performance when something is updated to memory (bitmap buffer) and not. 在这两种情况下,您都可以看到,当某些内容更新到内存(位图缓冲区)时,性能上存在巨大差异。

So what about off-screen canvas? 那么屏幕外的画布呢? The same would be the case with these as something needs to be updated in the off-screen canvas' buffer. 这些情况也是如此,因为需要在屏幕外画布缓冲区中更新某些内容。 The "only" thing it saves is updates to the browser's main buffer which may or may not be optimized. 它保存的“唯一”内容是浏览器主缓冲区的更新,可能会也可能不会进行优化。

If you use Chrome DevTools can use the Timeline panel to view page performance. 如果您使用Chrome DevTools,可以使用“ 时间轴”面板查看页面性能。

时间轴面板概述

Another option is to enable the "Show paint rectangles" option in the web inspector. 另一个选项是在Web检查器中启用“显示绘制矩形”选项。 Which will draw a square around the area that is repainted. 这将在重新绘制的区域周围画一个正方形。 Web Inspector > Settings > General > Rendering : Show paint rectangles Web Inspector>设置>常规>渲染:显示绘制矩形

显示绘画矩形


Resource: 资源:

Paul Irish has a really good blog post on this, Why Moving Elements With Translate() Is Better Than Pos:abs Top/left . 保罗爱尔兰有一个非常好的博客文章, 为什么移动元素与翻译()比Pos更好:abs上/左

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM