아주 아주 아주 큰 사업부


109

내 프로젝트 ( 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>

54
[OT] 600K 글꼴 크기. 시력 이 매우 나쁜 사람들을위한 접근성 기능이어야 합니까? ;-)
— geert3 2014

61
@ geert3 확실 해요 그것의 달 궤도 웹 브라우저
— 데이비드 윌킨스

3
귀하의 데모는 크롬 41.0.2236.0 dev에-m 부드러운
— 부두 뤽 Gendreau을

11
나는 카나리아 (41.0.2241.0 카나리아)에 있으며 여전히 지연이 발생합니다. 너희들이 대신 게임 장비의 노트북을 시도해야합니다, 당신은 그것을 볼 수 있습니다
— markasoftware

3
일반적인 믿음과는 달리 IE는 실제로 대부분의 페이지를 렌더링하는 데 Chrome보다 빠릅니다. 하지만 자바 스크립트 엔진은 조금 느립니다.
— Falanwe

답변:


62

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


27
그의 질문에 대한 직접적인 대답은 아니지만 그의 초기 문제 (Chrome의 느린 응답)에 대한 잠재적 인 해결책입니다. 상자 밖에서 생각하는 것이 좋습니다, IMHO.
— geert3 2014-12-08

여기에서 완벽하게 작동하는 것 같습니다 : gget.it/e0ubdh67/big-div-test_fixed.html . 이유를 아십니까? :)
— Basj 2014

2
추측 만 할 수 있습니다. fixed레이아웃이 덜 복잡하고 아마도 더 많은 최적화를 할 수 있습니다. 당신이 ;-) 의미하지만 내가 렌더링 엔진의 소스 코드를 못 봤어
— geert3

1
이 답변과 ViliusL이 제공 한 답변은 서로 다른 사람들이 동일한 "댓글 남기기"댓글을 가지고 있습니다. 얼마나 멋진가요?
— Joe

2
@Joe 이들은 중재자가 사용하기 위해 StackOverflow에서 제공하는 표준 답변 집합에서 가져온 것입니다. 일부는 더 적당히 조절해야합니다.
— geert3 2014

42

transform대신 사용 top/left:

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

jsFiddle의 라이브 데모 .


2
아주 이상한 일이 : 당신의 jsFiddle, 그것은 참으로 크롬과 빠릅니다. 내가 그랬어 정확히 : 여기 내 원래의 코드에서 제안하는 수정 gget.it/1owxq8kr/big-div-test_transform.html ? :(이 가능하다 어떻게 그것은 당신의 jsFiddle 같은보고, 마지막 링크가 크롬에 느린을 ! [참고 : 기적적으로 geert3의 답변이 작동하는 것 같습니다. 이유는 모르겠지만 작동합니다. gget.it/e0ubdh67/big-div-test_fixed.html]
— Basj

@Basj 아마도 버전에 따라 다르 겠지만, 내 Chrome (39.0.2171.71m)은 댓글에 링크 된 페이지를 FF만큼 부드럽고 빠르게 패닝합니다. 어쨌든 위치를 설정 fixed하면 텍스트 흐름에서 요소가 제거되고 많은 다시 렌더링이 절약됩니다. transformMDN 의 문서에서 "... 스택 컨텍스트가 생성 될 것입니다.이 경우 객체는 위치에 대한 포함 블록 역할 : 포함 된 고정 요소"라고 말합니다.
— Teemu

2
이상하게도 Chrome 39.0.2171.71 m도 있습니다 ... 그리고 gget.it/1owxq8kr/big-div-test_transform.html 팬은 원래 버전만큼 느리게 진행됩니다 (질문 자체에서). Oohhh 가능성은 하드웨어 가속에 따라 달라집니다 : 나는 가난한 그래픽 칩 노트북을 가지고 있기 때문에 아마, 어떤 하드웨어 가속이 없습니다 ...
— Basj

1
래퍼 추가 @Basj <div style="position:relative;min-height: 900px;">Your's divs</div>jsFiddle는 그렇게
— 알폰소 Rubalcava

1
@AlfonsoRubalcava 오 ok ... 이것은 jsfiddle이 매끄럽고 직접 링크가 매끄럽지 않은 이유를 설명합니다 (Chrome) : gget.it/1owxq8kr/big-div-test_transform.html ! 감사! 성능의 향상은에서 온다 그래서 position:relativepropbably, geert3의 대답에 유사하다
— Basj

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

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

  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

흥미 롭군. Firefox가 10k에서 멈추고 Chrome이 원래 크기를 렌더링하려고한다는 점을 염두에두고있는 요소가 있습니까? (향후 참조를 위해 흥미로울 것입니다). 미리 감사드립니다 @ViliusL!
— Basj

1
@Basj는 각 브라우저에 대해 최대 글꼴 크기를 추가했으며 (오늘 테스트 됨) 파이어 폭스의 경우 2k입니다.
— ViliusL 2014

@ViliusL에 감사드립니다! 실제로 FF는 FF를 제한 font-size하고 이것이 FF에서 느리지 않는 이유가 될 수 있습니다. 하지만 IE에서도 매우 느 렸어 야하는데 ... 이상합니다!
— Basj 2014-12-08

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

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

사용 display: table및 table-layout:fixed사업부에, 또는 사업부 포장 테이블. HTML에서 :

HTML 테이블 모델은 작성자의 도움으로 사용자 에이전트가 렌더링을 시작하기 전에 모든 데이터를 기다릴 필요없이 점진적으로 (즉, 테이블 행이 도착할 때) 테이블을 렌더링 할 수 있도록 설계되었습니다.

사용자 에이전트가 한 번의 패스로 테이블 형식을 지정하려면 작성자가 사용자 에이전트에 다음 사항을 알려야합니다.

테이블의 열 수입니다. 이 정보를 제공하는 방법에 대한 자세한 내용은 테이블의 열 수 계산 섹션을 참조하십시오. 이 열의 너비. 이 정보를 제공하는 방법에 대한 자세한 내용은 열 너비 계산 섹션을 참조하십시오.

보다 정확하게는 COLGROUP 및 COL 요소의 조합을 사용하여 열 너비를 지정할 때 사용자 에이전트가 단일 패스로 테이블을 렌더링 할 수 있습니다. 열이 상대 또는 백분율 용어로 지정된 경우 (열 너비 계산 섹션 참조) 작성자는 테이블 자체의 너비도 지정해야합니다.

증분 표시의 경우 브라우저에는 열 수와 너비가 필요합니다. 테이블의 기본 너비는 현재 창 크기 (width = "100 %")입니다. TABLE 요소의 너비 속성을 설정하여 변경할 수 있습니다. 기본적으로 모든 열의 너비는 동일하지만 테이블 데이터가 시작되기 전에 하나 이상의 COL 요소로 열 너비를 지정할 수 있습니다.

나머지 문제는 열 수입니다. 어떤 사람들은 테이블의 첫 번째 행이 수신 될 때까지 기다리는 것을 제안했지만 셀에 많은 내용이있는 경우 시간이 오래 걸릴 수 있습니다. 전체적으로 증분 표시가 필요한 경우 작성자가 TABLE 요소의 열 수를 명시 적으로 지정하도록하는 것이 더 합리적입니다.

작성자는 여전히 증분 표시를 사용할지 또는 셀 내용에 맞게 테이블 크기를 자동으로 조정할지 사용자 에이전트에 알리는 방법이 필요합니다. 2 단계 자동 크기 조정 모드에서 열 수는 첫 번째 단계에 의해 결정됩니다. 증분 모드에서는 열 수를 앞에 명시해야합니다 (COL 또는 COLGROUP 요소 사용).

및 CSS :

17.5.2.1 고정 테이블 레이아웃

이 (빠른) 알고리즘을 사용하면 테이블의 가로 레이아웃이 셀의 내용에 의존하지 않습니다. 표의 너비, 열 너비, 테두리 또는 셀 간격에만 의존합니다.

테이블의 너비는 'width'속성을 사용하여 명시 적으로 지정할 수 있습니다. 'auto'값 ( 'display : table'및 'display : inline-table'모두)은 자동 테이블 레이아웃 알고리즘을 사용함을 의미합니다. 그러나 테이블이 정상적인 흐름에서 블록 수준 테이블 ( 'display : table') 인 경우 UA는 10.3.3의 알고리즘을 사용하여 너비를 계산하고 고정 된 테이블 레이아웃을 적용 할 수 있습니다 (그럴 필요는 없음). 지정된 너비는 '자동'입니다.

참고 문헌

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.