IT박스

아주 아주 아주 큰 사업부

itboxs 2020. 8. 10. 07:50
반응형

아주 아주 아주 큰 사업부


내 프로젝트 ( BigPictu.re 또는 bigpicture.js GitHub 프로젝트 참조 )의 경우 잠재적으로 매우, 매우, 매우 큰 <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>

로 변경하면 position: fixed속도가 빨라지는 것 같습니다.


transform대신 사용 top/left:

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

jsFiddle의 라이브 데모 .


  1. 첫 번째 퀘스트 "왜"에 대한 답변. 문제 중 하나는 글꼴 크기 입니다. 글꼴 크기가 600000px이면 대부분의 브라우저는 너무 높게 표시되고 더 작게 렌더링되는 반면 크롬은 원래 크기를 렌더링하려고합니다. 크롬이 요청한 스타일로 큰 글자를 매우 빠르게 다시 칠할 수없는 것 같습니다.

그러나 Teemu와 geert3 답변을 결합하면-transform 및 position : fixed를 사용하면 큰 글꼴에서도 크롬이 훨씬 더 빠르게 작동합니다.

  1. 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/

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

In addition to Teemu's answer of using 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:

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.


@Teemus' answer almost does it all.

Use transform with translate3d instead of top/left.

translate3d enables hardware acceleration.

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

A live demo at jsFiddle.


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.

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.

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.

I would suggest that this should be filed as a Chrome bug.


Use display: table and table-layout:fixed on the div, or a table wrapping the div. In 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).

and 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'.

References

참고URL : https://stackoverflow.com/questions/27356273/a-very-very-very-big-div

반응형