Очень, очень, очень большой div

Для моего проекта (см. BigPicture.bi или проект 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>

Ответ 1

Переход на position: fixed, кажется, ускоряет работу.

Ответ 3

  • Ответ на первый квест "почему". Одна из проблем - размер шрифта. у вас есть размер шрифта 600000px, большинство браузеров будет считать его слишком высоким и сделать меньше, в то время как хром пытается отобразить оригинальный размер. Похоже, хром не может перекрасить такие большие буквы с запрошенными стилями очень быстро.

Но объединение ответов Teemu и geert3 - с использованием преобразования и положения: фиксированный, делает хром работает намного быстрее даже с большими шрифтами.

  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

Ответ 4

В дополнение к ответу Teemu на использование перевода:

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

Для чего вы также должны использовать префиксы других поставщиков, вы можете просто исправить это, используя это на теле:

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

и это на html:

height: 100%;

это, однако, отключит прокрутку. Итак, что бы я сделал, добавьте событие mousedown в тело и примените эти стили, используя класс css всякий раз, когда срабатывает mousedown, и удаляет этот класс на mouseup.

Ответ 5

Ответ

@Teemus почти все делает.

Используйте transform с translate3d вместо top/left.

translate3d позволяет аппаратное ускорение.

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

Живая демонстрация в jsFiddle.

Ответ 6

Я проанализировал это, и я обнаружил, что исходная проблема, связанная с архитектурой отображения Chrome, и ее использование фоновых потоков для отображения страницы.

Если вы хотите иметь быструю визуализацию, перейдите в chrome: flags, выделите настройку Impl-side painting и установите "Disabled", затем перезапустите браузер - mousemove будет плавным.

То, что я обнаружил, - это то, что если вы включите счетчик FPS, сообщенный FPS в этом сценарии все еще очень высок, хотя фактическая производительность на экране очень низкая. Мое предварительное объяснение (не являющееся экспертом по архитектуре экрана Chrome) заключается в том, что если поток и отображение пользовательского интерфейса находятся в отдельных потоках, тогда в рендеринге div может возникнуть конфликт в случае, когда поток потоков и потока пользовательского интерфейса находится на тот же поток, поток пользовательского интерфейса не может отправлять сообщения быстрее, чем может отображаться поток пользовательского интерфейса.

Я бы предположил, что это должно быть зарегистрировано как ошибка Chrome.

Ответ 7

Используйте display: table и table-layout:fixed в div, или таблицу, обернутую div. В HTML:

Модель таблицы HTML была разработана таким образом, чтобы при помощи автора пользовательские агенты могли визуализировать таблицы поэтапно (т.е. по мере поступления строк таблицы), а не ждать до всех данных до начала рендеринга.

Чтобы пользовательский агент мог форматировать таблицу за один проход, авторы должны сообщить агенту пользователя:

Число столбцов в таблице. Для получения подробной информации о том, как предоставить эту информацию, обратитесь к разделу, посвященному расчёту количества столбцов в таблице.    Ширина этих столбцов. Подробные сведения о том, как предоставить эту информацию, можно найти в разделе, посвященном вычислению ширины столбцов.

Более точно, пользовательский агент может отображать таблицу за один проход, когда ширина столбца задается с использованием комбинации элементов COLGROUP и COL. Если какой-либо из столбцов указан в относительном или процентном выражении (см. Раздел о вычислении ширины столбцов), авторы должны также указать ширину самой таблицы.

Для инкрементного отображения браузеру требуется количество столбцов и их ширина. Ширина таблицы по умолчанию - это текущий размер окна (width = "100%" ). Это можно изменить, установив атрибут width элемента TABLE. По умолчанию все столбцы имеют одинаковую ширину, но вы можете указать ширину столбцов с одним или несколькими элементами COL до начала ввода данных таблицы.

Остальная проблема - количество столбцов. Некоторые люди предложили дождаться, пока не будет получена первая строка таблицы, но это может занять много времени, если в ячейках много контента. В целом имеет смысл, когда требуется инкрементное отображение, чтобы заставить авторов явно указывать количество столбцов в элементе TABLE.

Авторы по-прежнему нуждаются в способе сообщать пользовательским агентам, следует ли использовать инкрементный дисплей или автоматически сортировать таблицу, чтобы соответствовать содержимому ячейки. В режиме автоматического калибровки двух проходов количество столбцов определяется первым проходом. В инкрементном режиме количество столбцов должно быть указано спереди (с элементами COL или COLGROUP).

и CSS:

17.5.2.1 Фиксированный макет таблицы

С помощью этого (быстрого) алгоритма горизонтальная компоновка таблицы не зависит от содержимого ячеек; это зависит только от ширины таблицы, ширины столбцов и границ или расстояний между ячейками.

Ширина таблицы может быть явно указана с использованием свойства width. Значение "auto" (для "display: table" и "display: inline-table" ) означает использование автоматического алгоритма компоновки таблиц. Однако, если таблица представляет собой таблицу уровня блока ( "display: table" ) в обычном потоке, UA может (но не обязательно) использовать алгоритм 10.3.3 для вычисления ширины и применять фиксированный макет таблицы, даже если указанная ширина - "авто".

Ссылки