아주 아주 아주 큰 사업부


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: tabletable-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.