一个非常非常大的div


109

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

我知道使用我所使用的简单方法可能会导致性能降低,但是我没想到它仅适用于Chrome!

如果测试此小页面(请参见下面的代码),则平移(单击并拖动)将是:

  • 在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>

54
[OT] 600K字体大小。必须是人的辅助功能有非常糟糕的视力?;-)
geert3

61
@ geert3我确定它是用于绕月球运行的网络浏览器
David Wilkins

3
您的演示在Chrome 41.0.2236.0 dev-m中很流畅
Pier-Luc Gendreau

11
我在金丝雀(41.0.2241.0金丝雀)中,我仍然滞后。你们应该在笔记本电脑上而不是在游戏平台上试用它,您会看到它
markasoftware 2014年

3
与普遍的看法相反,IE渲染大多数页面实际上比Chrome快。虽然它的JavaScript引擎要慢一些。
Falanwe 2014年

Answers:


62

更改为position: fixed似乎可以加快速度。


27
这不是他所提问题的直接答案,但可以解决他最初遇到的问题(Chrome中的响应缓慢)。恕我直言,应该鼓励跳出框框思考。
geert3

在这里,它似乎工作得很完美:gget.it/e0ubdh67/big-div-test_fixed.html。你知道为什么吗 ?:)
Basj 2014年

2
我只能猜。fixed布局显然不那么复杂,也许他们可以做更多的优化。但是我没有看过渲染引擎的源代码,如果您的意思是;-)
geert3

1
这个答案和ViliusL提供的答案,都是由不同的人发表的相同的“发表评论”评论。多么酷啊?

2
@Joe这些来自StackOverflow提供的一组标准答案,供主持人使用。有些人需要更温和地缓和。
geert3 2014年

42

使用transform代替top/left

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

jsFiddle上的现场演示


2
一个非常奇怪的事情:在您的jsFiddle中,Chrome的确确实快速。我完全按照您在原始代码中提出的建议进行了修改:gget.it/1owxq8kr/big-div-test_transform.html,而最后一个链接在Chrome上运行缓慢:(这怎么可能?它看起来与您的jsFiddle相同[注:奇迹般地,geert3的答案似乎有效,我不知道为什么,但是有效:gget.it/e0ubdh67/big-div-test_fixed.html]
Basj 2014年

@Basj也许这取决于版本,我的Chrome(39.0.2171.71 m)可以使您评论中链接的页面像FF一样流畅,快速。无论如何,将位置设置为fixed可以使元素脱离文本流,并节省大量重新渲染。在transformMDN 的文档中说:“ ...将创建一个堆栈上下文。在这种情况下,对象将充当位置的包含块:其中包含的固定元素。”
Teemu 2014年

2
奇怪,我还有Chrome 39.0.2171.71 m ...和gget.it/1owxq8kr/big-div-test_transform.html运行缓慢,速度与我的原始版本一样慢(在问题本身中)。哦,这可能取决于硬件加速:我可能没有硬件加速,因为我有一台笔记本电脑的图形芯片质量很差……
Basj 2014年

1
@Basj添加一个包装器<div style="position:relative;min-height: 900px;">Your's divs</div>jsFiddle也是这样
阿方索·卢巴尔卡瓦

1
@AlfonsoRubalcava哦,好吧...这说明了为什么jsfiddle平滑且直接链接不平滑(Chrome):gget.it/1owxq8kr/big-div-test_transform.html!谢谢!因此,性能的提高可能来自position:relativegeert3的答案
Basj 2014年

22
  1. 回答第一个任务“为什么”。问题之一是字体大小。您的字体大小为600000px,大多数浏览器会认为它太高而渲染得更小,而chrome则尝试渲染原始大小。看起来chrome无法以您要求的样式快速重绘这么大的字母。

但是结合使用Teemu和geert3答案-使用transform和position:fixed,即使使用大字体,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

6
确实如此。OP提出了两个问题,第一个问题得到了回答:“为什么FF,IE能够正确处理而不是Chrome?”
Hans Roerdinkholder 2014年

有趣。您是否有一些想法表明Firefox停止在10k,Chrome尝试渲染原始大小?(这很有趣,以备将来参考)。在此先感谢@ViliusL!
Basj 2014年

1
@Basj为每个浏览器添加了最大字体大小(今天经过测试),对于Firefox,它的大小为2k。
ViliusL 2014年

非常感谢@ViliusL!实际上,FF限制了font-size,这可能是FF不慢的原因。但是那时它在IE上也应该非常慢,但这不是...奇怪!
Basj 2014年

4

除了Teemu使用翻译的答案:

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

您还应该使用其他供应商前缀,您可以通过在主体上使用以下代码简单地解决此问题:

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

而这在HTML上:

height: 100%;

但是,这将禁用滚动。所以我要做的是,mousedown在主体上添加一个事件,并在每次mousedown触发时使用css类应用这些样式,然后在上删除该类mouseup


我试图在这里添加您提到的内容:gget.it/0ufheqmt/big-div-test_prisonersolution.html,这是您的意思吗?在这里,使用Chrome拖动仍然很慢。你也一样吗 (PS:我不解地问:你认为做这些CSS的修改,而不是使用style.transform使用transform?)。顺便感谢您对@Prisoner的回答!
Basj 2014年

2

@Teemus的答案几乎可以解决所有问题。

transform 与一起translate3d使用而不是top/left

translate3d 启用硬件加速。

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

jsFiddle上的现场演示


1

经过分析,我发现最初的问题与Chrome显示架构及其使用后台线程渲染页面有关。

如果要快速渲染,请进入chrome:flags,滚动到设置Impl-side painting,并设置为“ Disabled”,然后重新启动浏览器-mousemove将会很流畅。

我发现,如果启用了FPS计数器,即使实际的屏幕性能非常低,在这种情况下报告的FPS仍然很高。我的初步解释(不是Chrome显示架构专家)是,如果UI线程和显示位于单独的线程上,则div呈现中可能存在争用-如果UI线程和呈现线程位于相同的线程,UI线程发送消息的速度不能超过UI线程可以呈现的速度。

我建议将其记录为Chrome错误。


1

在div或包含div的表格上使用display: tabletable-layout:fixed。在HTML中:

HTML表模型已经过设计,因此在作者的帮助下,用户代理可以递增地呈现表(即,当表行到达时),而不必在开始呈现之前等待所有数据。

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

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

更准确地说,当使用COLGROUP和COL元素的组合指定列宽时,用户代理可以单次渲染表。如果以相对或百分比形式指定了任何列(请参见有关计算列宽的部分),那么作者还必须指定表本身的宽度。

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

剩下的问题是列数。有人建议等待直到收到表的第一行,但是如果单元格中的内容很多,这可能会花费很长时间。总体而言,当需要增量显示时,让作者显式指定TABLE元素中的列数更有意义。

作者仍然需要一种方法来告诉用户代理是使用增量显示还是自动调整表格大小以适合单元格内容。在两遍自动调整大小模式下,列数由第一遍确定。在增量模式下,必须预先说明列数(使用COL或COLGROUP元素)。

和CSS:

17.5.2.1固定表格布局

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

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

参考资料

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.