Очень, очень, очень большой div
для моего проекта (см. BigPictu.re или bigpicture.проект на JS на GitHub), Я должен иметь дело с потенциально очень, очень, очень большой <div> контейнер.
Я знал, что существует риск плохой работы с простым подходом, который я использую, но я не ожидал, что он будет в основном присутствовать ... Только хром!
Если вы тест эта небольшая страница (см. код ниже), панорамирование (нажмите + перетащите) будет:
- нормальный / гладкий на 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>
7 ответов:
использовать
transformвместоtop/left:container.style.transform = 'translate(' + container.x + 'px, ' + container.y + 'px)';
- ответ на первый квест "почему". Одна из проблем размер шрифта. у вас есть размер шрифта 600000px, большинство браузеров увидят его слишком высоким и уменьшат, в то время как chrome пытается отобразить исходный размер. Похоже, chrome не может перекрасить такие большие буквы с запрошенными стилями очень быстро.
но объединение ответов Teemu и geert3 - использование transform и position:fixed, делает chrome работает намного быстрее даже с большими шрифтами.
- ответ на 2-й вопрос: "есть способ ... не пытаться отобразить всю страницу" - вы можете попробовать применить действие мыши для элементов в контейнере, а не для всего контейнера.
максимальные размеры шрифта: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
в дополнение к ответу Teemu на использование translate:
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.
@Teemus ответ почти все это делает.
использовать
transformСtranslate3dвместоtop/left.
translate3dобеспечивает аппаратное ускорение.container.style.transform = 'translate3d(' + container.x + 'px, ' + container.y + 'px, 0)';
Я проанализировал это и обнаружил, что исходная проблема связана с архитектурой отображения Chrome и ее использованием фоновых потоков для визуализации страницы.
Если вы хотите иметь быстрый рендеринг, перейдите в chrome: flags, прокрутите до настройки Impl-side painting и установите "Disabled", затем перезапустите браузер - mousemove будет плавным.
Я обнаружил, что если вы включите счетчик FPS, сообщенный FPS в этом сценарии все еще очень высок, даже если фактическая производительность на экране очень низкая. Мое предварительное объяснение (не будучи экспертом по архитектуре отображения Chrome) заключается в том, что если поток пользовательского интерфейса и отображение находятся в разных потоках, то в рендеринге div может возникнуть конфликт - в случае, когда поток пользовательского интерфейса и поток рендеринга находятся в одном потоке, поток пользовательского интерфейса не может отправлять сообщения быстрее, чем поток пользовательского интерфейса может отображать.
Я бы предложил, чтобы это было подано как ошибка Chrome.
использовать
display: tableиtable-layout:fixedна div или таблице, обертывающей div. В HTML:модель таблиц HTML была разработана таким образом, что с помощью автора агенты пользователей могут отображать таблицы постепенно (т. е. по мере поступления строк таблицы), а не ждать всех данных перед началом визуализации.
для того, чтобы пользовательский агент отформатировал таблицу за один проход, авторы должны сообщить пользовательскому агенту:
количество столбцов в таблице стол. Пожалуйста, обратитесь к разделу расчета количества столбцов в таблице для получения подробной информации о том, как предоставить эту информацию. Ширина этих колонн. Пожалуйста, обратитесь к разделу по расчету ширины столбцов для сведения о том, как предоставить эту информацию.
более точно, агент пользователя может отображать таблицу за один проход, когда ширина столбцов задается с использованием комбинации элементов COLGROUP и COL. Если какой-либо из столбцов указан в поле относительный или процентные условия (см. раздел по расчету ширины столбцов), авторы также должны указать ширину самой таблицы.
для инкрементного отображения браузеру требуется количество столбцов и их ширина. По умолчанию ширина таблицы текущий размер окна (ширина="100%"). Это можно изменить, установив атрибут width элемента таблицы. По умолчанию все столбцы имеют одинаковую ширину, но вы можете указать ширину столбцов с одним или несколькими элементами COL до этого данные таблицы начинаются.
остальная проблема-это количество столбцов. Некоторые люди предложили подождать, пока не будет получена первая строка таблицы, но это может занять много времени, если ячейки имеют много содержимого. В целом, когда требуется инкрементное отображение, имеет смысл заставить авторов явно указать количество столбцов в элементе таблицы.
авторам по-прежнему нужен способ сообщить агентам пользователей, следует ли использовать инкрементные отображение или автоматическое изменение размера таблицы в соответствии с содержимым ячейки. В двухпроходном режиме автоматической калибровки количество столбцов определяется первым проходом. В инкрементном режиме количество столбцов должно быть указано заранее (с элементами COL или COLGROUP).
и CSS:
17.5.2.1 фиксированный макет таблицы
С помощью этого (быстрого) алгоритма горизонтальная компоновка таблицы не зависит от содержимого ячеек; это только зависит от ширины таблицы, ширины столбцов и границ или интервала между ячейками.
ширина таблицы может быть задана явно с помощью свойства 'width'. Значение ' auto '(как для' display: table', так и для' display: inline-table') означает использование алгоритма автоматической компоновки таблиц. Однако, если таблица является таблицей уровня блока ('display: table') в нормальном потоке, UA может (но не должен) использовать алгоритм 10.3.3 для вычисления ширины и применения фиксированной компоновки таблицы, даже если заданная ширина- "авто".
ссылки
Comments