一个非常非常非常大的div

对于我的项目(请参阅BigPicture.bi或bigpicture.js GitHub项目 ),我必须处理一个非常非常非常大的<div>容器。

我知道用我使用的简单方法存在性能不佳的风险,但是我没有想到,它大部分只出现在Chrome浏览器中。

如果你testing这个小页面 (见下面的代码),平移(单击+拖动)将是:

  • 在Firefox上正常/平滑
  • 即使在Internet Explorer上也正常/平滑
  • 在Chrome上非常慢(几乎崩溃)!

当然,我可以添加一些代码(在我的项目中),当你放大的时候,可能会隐藏很大的文字。 但是, 为什么Firefox和Internet Explorer正确处理它,而不是Chrome?

有没有在JavaScript,HTML或CSS的方式告诉浏览器不要尝试渲染整个页面(这是10000像素宽这里)的每一个行动? (只呈现当前的视口!)


 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <style> html, body { overflow: hidden; min-height: 100%; } #container { position: absolute; min-height: 100%; min-width: 100%; } .text { font-family: "Arial"; position: absolute; } </style> </head> <body> <div id="container"> <div class="text" style="font-size: 600px; left:100px; top:100px">Small text</div> <div class="text" style="font-size: 600000px; left:10000px; top:10000px">Very big text</div> </div> <script> var container = document.getElementById('container'), dragging = false, previousmouse; container.x = 0; container.y = 0; window.onmousedown = function(e) { dragging = true; previousmouse = {x: e.pageX, y: e.pageY}; } window.onmouseup = function() { dragging = false; } window.ondragstart = function(e) { e.preventDefault(); } window.onmousemove = function(e) { if (dragging) { container.x += e.pageX - previousmouse.x; container.y += e.pageY - previousmouse.y; container.style.left = container.x + 'px'; container.style.top = container.y + 'px'; previousmouse = {x: e.pageX, y: e.pageY}; } } </script> </body> </html> 

改变position: fixed似乎加速了事情。

使用transform而不是top/left

 container.style.transform = 'translate(' + container.x + 'px, ' + container.y + 'px)'; 

在jsFiddle现场演示 。

  1. 回答第一个任务“为什么”。 问题之一是字体大小 。 您的字体大小为600000px,大多数浏览器会将其视为太高而呈现较小,而chrome会尝试呈现原始大小。 看起来像铬不能用你所要求的风格非常快地重新绘制这样的大字母。

但是,结合Teemu和geert3的答案 – 使用变换和位置:固定,使得即使使用大字体,chrome的工作速度也要快得多。

  1. 回答第二个问题:“是否有办法…不尝试渲染整个页面” – 您可以尝试对容器中的元素应用鼠标操作,而不是整个容器。

最大字体大小: http : //jsfiddle.net/74w7yL0a/

 firefox 34 - 2 000 px chrome 39 - 1 000 000 px safari 8 - 1 000 000 px ie 8-11 - 1 431 700 px 

除了Teemu使用translate的答案:

 container.style.transform = 'translate(' + container.x + 'px, ' + container.y + 'px)'; 

你也应该使用其他供应商的前缀,你可以简单的解决这个问题:

 height: 100%; width: 100%; position: relative; overflow: hidden; 

和这个HTML:

 height: 100%; 

这会,但是,禁用滚动。 所以我要做的是,在body上添加一个mousedown事件,并在触发mousedown时使用css类来应用这些样式,然后在mouseup上移除这个类。

@Teemus的答案几乎是这一切。

使用translate3d而不是top/left

translate3d启用硬件加速。

 container.style.transform = 'translate3d(' + container.x + 'px, ' + container.y + 'px, 0)'; 

在jsFiddle现场演示 。

我分析了这一点,我发现原来的问题涉及到Chrome显示器架构,以及它使用后台线程来渲染页面。

如果你想快速渲染,进入chrome:flags,滚动到Impl-side绘制的设置,并设置“Disabled”,然后重新启动浏览器 – 鼠标移动将平滑。

我发现,如果启用FPS计数器,则在这种情况下报告的FPS仍然非常高,即使屏幕上的实际性能很低。 我试探性的解释(不是Chrome显示器架构专家)是,如果UI线程和显示在不同的线程上,那么在渲染div的时候会有争用 – 在UI线程和渲染线程在相同的线程,UI线程不能发送消息比UI线程可以呈现更快。

我build议这应该被归档为Chrome的错误。

使用display: tabletable-layout:fixed在div上,或者一个包裹div的表格。 在HTML中:

HTML表格模型的devise使得在作者协助下,用户代理可以递增地呈现表格(即,当表格行到达时),而不必在开始呈现之前等待所有的数据。

为了使用户代理能够一次格式化表格,作者必须告诉用户代理:

表中的列数。 有关如何提供此信息的详细信息,请参阅计算表中列数的部分。 这些列的宽度。 有关如何提供此信息的详细信息,请参阅有关计算列宽的部分。

更确切地说,当使用COLGROUP和COL元素的组合来指定列宽时,用户代理可以单次渲染表格。 如果任何列以相对或百分比的方式指定(请参阅计算列的宽度一节),作者还必须指定表本身的宽度。

对于增量显示,浏览器需要列数和宽度。 表格的默认宽度是当前窗口大小(宽度=“100%”)。 这可以通过设置TABLE元素的width属性来改变。 默认情况下,所有列具有相同的宽度,但可以在表数据启动之前指定具有一个或多个COL元素的列宽。

剩下的问题是列数。 有些人build议等到表格的第一行被接收,但如果单元格内容很多,这可能需要很长时间。 总的来说,当需要增量显示时,让作者明确指定TABLE元素中的列数是更有意义的。

作者仍然需要告诉用户代理使用增量显示还是自动调整表格大小以适应单元格内容。 在两次自动resize模式中,列数由第一遍确定。 在增量模式下,列数必须在最前面(使用COL或COLGROUP元素)。

和CSS:

17.5.2.1固定表格布局

使用这种(快速)algorithm,表格的水平布局不依赖于单元格的内容; 它只取决于表的宽度,列的宽度以及边框或单元格间距。

表格的宽度可以用'width'属性明确指定。 'auto'的值(对于'display:table'和'display:inline-table')意味着使用自动表格布局algorithm。 但是,如果该表是正常stream程中的块级表('display:table'),则UA可以(但不必)使用10.3.3的algorithm计算宽度并应用固定表格布局,即使指定的宽度是'auto'。

参考

  • HTML 4:11.2,用于构build表格的元素
  • HTML 4:附录B,第5.1.2节:增量显示
  • HTML 5:用于处理行的algorithm
  • CSS2:17.5.2表宽度algorithm,“table-layout”属性
  • 美国网页devise标准文件草案| 表