javascript 一个非常非常非常大的div
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27356273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
A very, very, very big div
提问by Basj
For a project of mine (see BigPictu.reor bigpicture.js GitHub project), I have to deal with potentially a very, very, very big <div>
container.
对于我的一个项目(参见BigPictu.re或bigpicture.js GitHub 项目),我必须处理一个可能非常、非常、非常大的<div>
容器。
I knew there was a risk of poor performance with the simple approach I use, but I did not expect it to be mostly present with ... Chrome only!
我知道我使用的简单方法存在性能不佳的风险,但我没想到它主要存在于...仅 Chrome 中!
If you test this small page(see code below), panning (click + drag) will be:
如果你测试这个小页面(见下面的代码),平移(点击+拖动)将是:
- Normal / smooth on Firefox
- Normal / smooth even on Internet Explorer
- Very slow (nearly crashing) on Chrome!
- 在 Firefox 上正常/平滑
- 即使在 Internet Explorer 上也正常/流畅
- 在 Chrome 上非常慢(几乎崩溃)!
Of course, I could add some code (in my project) to do that when you're zoomed in a lot, text with potentially very very big font-size would be hidden. But still, why does Firefox and Internet Explorer handle it correctly and not Chrome?
当然,我可以添加一些代码(在我的项目中),当您放大很多时,可能会隐藏具有非常大字体大小的文本。但是,为什么 Firefox 和 Internet Explorer 可以正确处理它而不是 Chrome?
Is there a way in JavaScript, HTML, or CSS to tell the browser not to tryto render the whole page (which is 10000 pixels wide here) for every action?(only render the current viewport!)
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>
采纳答案by geert3
Changing to position: fixed
seems to speed things up.
更改为position: fixed
似乎可以加快速度。
回答by Teemu
回答by ViliusL
- Answer to first quest "why". One of problems are font size. you have font size 600000px, most browser will see it as too high and render smaller, while chrome tries to render original size. Looks like chrome can not repaint such big letters with your requested styles very fast.
- 回答第一个问题“为什么”。问题之一是字体大小。您的字体大小为 600000 像素,大多数浏览器会认为它太高并渲染得更小,而 chrome 会尝试渲染原始大小。看起来 chrome 不能用你要求的样式非常快地重新绘制这么大的字母。
But combining Teemu and geert3 answers - using transform and position:fixed, makes chrome works much more faster even with big fonts.
但是结合 Teemu 和 geert3 答案 - 使用变换和位置:固定,即使使用大字体,chrome 的工作速度也会更快。
- Answer to 2nd question: "Is there a way ... not to try to render the whole page" - you can try to apply mouse action for elements in container, not for whole container.
- 回答第二个问题:“有没有办法......不要尝试渲染整个页面” - 您可以尝试对容器中的元素而不是整个容器应用鼠标操作。
Maximum font sizes: http://jsfiddle.net/74w7yL0a/
最大字体大小: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
回答by Prisoner
In addition to Teemu's answer of using translate:
除了 Teemu 使用 translate 的回答:
container.style.transform = 'translate(' + container.x + 'px, ' + container.y + 'px)';
Which you should also use other vendor prefixes, You can simply fix this by using this on the body:
您还应该使用其他供应商前缀,您可以通过在主体上使用它来简单地解决此问题:
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
and this on html:
这在 html 上:
height: 100%;
this will, however, disable scrolling. So what I'd do is, add a mousedown
event to the body and apply those styles using a css class whenever mousedown
is triggered, and removing that class on mouseup
.
但是,这将禁用滚动。所以我要做的是,mousedown
向主体添加一个事件,并在mousedown
触发时使用 css 类应用这些样式,并在mouseup
.
回答by Koen.
@Teemus' answer almost does it all.
@Teemus 的回答几乎可以解决所有问题。
Use transform
with translate3d
instead of top/left
.
使用transform
withtranslate3d
而不是top/left
。
translate3d
enables hardware acceleration.
translate3d
启用硬件加速。
container.style.transform = 'translate3d(' + container.x + 'px, ' + container.y + 'px, 0)';
回答by Theodore Ferro
I analyzed this and I found that the original problem related to the Chrome display architecture, and its use of background threads to render the page.
我对此进行了分析,发现原来的问题与 Chrome 显示架构有关,以及它使用后台线程来呈现页面。
If you want to have fast rendering, go into chrome:flags, scroll to the setting Impl-side painting, and set "Disabled", then restart the browser - the mousemove will be smooth.
如果你想要快速渲染,进入 chrome:flags,滚动到设置 Impl-side Painting,并设置“Disabled”,然后重新启动浏览器 - mousemove 会很流畅。
What I found is that if you enable the FPS counter, the reported FPS in this scenario is still very high, even though the actual onscreen performance is very low. My tentative explanation (not being a Chrome display architecture expert) is that if the UI thread and display are on separate threads, then there can be contention in the rendering of the div - in the case where the UI thread and rendering thread is on the same thread, the UI thread cannot send messages faster than the UI thread can render.
我发现,如果启用 FPS 计数器,在这种情况下报告的 FPS 仍然很高,即使实际屏幕性能很低。我的初步解释(不是 Chrome 显示架构专家)是,如果 UI 线程和显示在不同的线程上,那么在 div 的渲染中可能会出现争用 - 在 UI 线程和渲染线程在同一个线程,UI 线程发送消息的速度不能快于 UI 线程渲染的速度。
I would suggest that this should be filed as a Chrome bug.
我建议这应该作为 Chrome 错误提交。
回答by Paul Sweatte
Use display: table
and table-layout:fixed
on the div, or a table wrapping the div. In HTML:
在 div 上使用display: table
和table-layout:fixed
,或者在 div 上使用一个表格。在 HTML 中:
The HTML table model has been designed so that, with author assistance, user agents may render tables incrementally (i.e., as table rows arrive) rather than having to wait for all the data before beginning to render.
In order for a user agent to format a table in one pass, authors must tell the user agent:
The number of columns in the table. Please consult the section on calculating the number of columns in a table for details on how to supply this information. The widths of these columns. Please consult the section on calculating the width of columns for details on how to supply this information.
More precisely, a user agent may render a table in a single pass when the column widths are specified using a combination of COLGROUP and COL elements. If any of the columns are specified in relative or percentage terms (see the section on calculating the width of columns), authors must also specify the width of the table itself.
For incremental display, the browser needs the number of columns and their widths. The default width of the table is the current window size (width="100%"). This can be altered by setting the width attribute of the TABLE element. By default, all columns have the same width, but you can specify column widths with one or more COL elements before the table data starts.
The remaining issue is the number of columns. Some people have suggested waiting until the first row of the table has been received, but this could take a long time if the cells have a lot of content. On the whole it makes more sense, when incremental display is desired, to get authors to explicitly specify the number of columns in the TABLE element.
Authors still need a way of telling user agents whether to use incremental display or to size the table automatically to fit the cell contents. In the two pass auto-sizing mode, the number of columns is determined by the first pass. In the incremental mode, the number of columns must be stated up front (with COL or COLGROUP elements).
HTML 表格模型的设计使得在作者的帮助下,用户代理可以增量地呈现表格(即,当表格行到达时),而不必在开始呈现之前等待所有数据。
为了让用户代理一次性格式化表格,作者必须告诉用户代理:
表中的列数。有关如何提供此信息的详细信息,请参阅有关计算表中列数的部分。这些列的宽度。有关如何提供此信息的详细信息,请参阅有关计算列宽的部分。
更准确地说,当使用 COLGROUP 和 COL 元素的组合指定列宽时,用户代理可以在一次通过中呈现表格。如果任何列以相对或百分比形式指定(请参阅有关计算列宽的部分),作者还必须指定表格本身的宽度。
对于增量显示,浏览器需要列数及其宽度。表格的默认宽度是当前窗口大小(width="100%")。这可以通过设置 TABLE 元素的 width 属性来改变。默认情况下,所有列都具有相同的宽度,但您可以在表数据开始之前使用一个或多个 COL 元素指定列宽。
剩下的问题是列数。有些人建议等到收到表格的第一行,但如果单元格有很多内容,这可能需要很长时间。总的来说,当需要增量显示时,让作者明确指定 TABLE 元素中的列数更有意义。
作者仍然需要一种方法来告诉用户代理是使用增量显示还是自动调整表格大小以适应单元格内容。在两遍自动调整大小模式下,列数由第一遍决定。在增量模式下,必须预先说明列数(使用 COL 或 COLGROUP 元素)。
and CSS:
和 CSS:
17.5.2.1 Fixed table layout
With this (fast) algorithm, the horizontal layout of the table does not depend on the contents of the cells; it only depends on the table's width, the width of the columns, and borders or cell spacing.
The table's width may be specified explicitly with the 'width' property. A value of 'auto' (for both 'display: table' and 'display: inline-table') means use the automatic table layout algorithm. However, if the table is a block-level table ('display: table') in normal flow, a UA may (but does not have to) use the algorithm of 10.3.3 to compute a width and apply fixed table layout even if the specified width is 'auto'.
17.5.2.1 固定表格布局
使用这种(快速)算法,表格的水平布局不依赖于单元格的内容;它仅取决于表格的宽度、列的宽度以及边框或单元格间距。
可以使用 'width' 属性明确指定表格的宽度。'auto' 值(对于 'display: table' 和 'display: inline-table')意味着使用自动表格布局算法。但是,如果表格是正常流程中的块级表格('display: table'),则 UA 可以(但不是必须)使用 10.3.3 的算法来计算宽度并应用固定表格布局,即使指定的宽度是“自动”。
References
参考