2015-05-14 2 views
1

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

Мое текущее решение включает в себя рисование фона на холсте, а затем использование этого рисунка в качестве фонового изображения на ячейках через URI данных.

cell.css({backgroundImage:'url(' + canvas.toDataURL('image/png')+ ')' }); 

Это хорошо работает, но исходный HTML становится довольно большим со всем дублированием из кодированного изображения, и в конечном счете делает некоторые браузеры бороться.

Есть ли способ как-то повторно использовать один и тот же URI данных, не дублируя его?

Другие идеи Я рассмотрел: - непосредственно использовать элемент холста в качестве фона с -webkit-canvas или -moz-element, но это, кажется, не очень совместимы с Internet Explorer. - абсолютно поместите холст в каждую ячейку и перерисуйте содержимое, но это не очень эффективно, когда мы добираемся до сотен строк.

+0

Как часто освещает ваше изображение? – Ejaz

+0

Обновление изображений из-за взаимодействия с пользователем, поэтому оно может быть несколько раз в секунду или вообще не работать. –

ответ

1

Вариант 1:

Посмотрите в использовании Canvas2Blob.

В принципе вы можете получить строку URL, вызвав URL.createObjectURL(blob); где blob является объект, возвращаемый из polyfill canvas.toBlob(function (blob) {...});

Преимущество этого в том, что Blob является 3/4 размер строки dataURI из-кодирования , и он не должен быть интенсивным при работе с памятью/процессором 100 секунд.

Вариант 2:

Если вы действительно хотите использовать canvas.toDataURL('image/png'); затем сохранить его в строковую переменную как

var str = canvas.toDataURL('image/png'); 
// ... 
cell.css({backgroundImage:'url(' + str + ')' }); 

В зависимости от реализации браузера, вызов .toDataURL() может быть очень дорогой вызов функции , и поскольку для всех ячеек нужен один и тот же фон, вам лучше будет просто сохранить его в строке.

+0

Я действительно использую вариант 2 в своем коде, моя проблема с ним - это в основном раздутый источник html, который замедляет работу браузера, когда есть много строк. Вместо вывода всей строки я действительно хотел просто ссылаться на одну закодированную копию изображения. Вариант 1 выглядит интересным, у меня будет игра с ним. –

+0

@Coin_op Вариант 1 намного лучше, потому что URL-адрес объекта примерно такой же длины, как и обычный URL-адрес, например примерно 20 символов. Это, безусловно, тонна лучше, чем dataURI. –

+0

. Кажется, это выглядит лучше с точки зрения HTML, но оно не отображается так быстро, я получаю небольшое мерцание при загрузке нового URL-адреса, я не уверен, что это будет приемлемо еще. –

1

Есть ли способ как-то повторно использовать один и тот же URI данных, не дублируя его?

Нет, Data-URI - это просто текстовое представление двоичных данных, здесь создан файл PNG (или JPEG). Если вам нужно изменить контент, сначала необходимо изменить двоичные данные, а затем закодировать URI данных на основе этого. Поэтому он не может быть повторно использован.

toDataURL() также очень медленный процесс, и использование этого метода также включает в себя построение, кодирование, сжатие, разбор, декомпрессию и декодирование данных растрового изображения каждый раз, это на вершине кодирования/декодирования файла на и из базы -64.

Как эффективно обновлять динамически нарисованный фон на сотни элементов

Вот что я хотел бы сделать:

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

Пример

var table = document.querySelector("table"), 
 
    canvas = document.querySelector("canvas"), 
 
    ctx = canvas.getContext("2d"); 
 

 
getArray(); // and on resize if needed 
 

 
function getArray() { 
 
    // todo: iterate table here to find sizes for each cell. 
 
    // For simplicity just the table width and height is measured in this example: 
 
    var rect = table.getBoundingClientRect(); 
 
    canvas.width = rect.width; 
 
    canvas.height = rect.height; 
 
} 
 

 
// render for demo - 
 
(function loop() { 
 
    render(); 
 
    requestAnimationFrame(loop) 
 
})(); 
 

 
function render() { 
 
    var cw = canvas.width * 0.5, 
 
     ch = canvas.height * 0.5; 
 
    for(var y = 0; y < 2; y++) { 
 
    for(var x = 0; x < 2; x++) { 
 
     ctx.fillStyle = "hsl(" + (360*Math.random()) + ",80%,70%)"; 
 
     ctx.fillRect(x * cw, y * ch, cw, ch); 
 
    } 
 
    } 
 
}
div {position:relative} 
 
canvas, table {position:absolute; left:0; top:0} 
 
table {border:1px solid #000}
<div> 
 
    <canvas></canvas> 
 
    <table> 
 
    <tr> 
 
     <td>Cell</td> 
 
     <td>Cell</td> 
 
    </tr> 
 
    <tr> 
 
     <td>Cell</td> 
 
     <td>Cell</td> 
 
    </tr> 
 
    </table> 
 
</div>

кэширование изображения

Другой способ заключается в заранее создать массив с изображениями и настройки их источник данных-uri.

Тогда используйте изображение как фоновое изображение для таблицы.

+0

Я понимаю, что URI данных необходимо регенерировать каждый раз, когда изображение меняется, но мне было интересно, можно ли использовать эти данные более одного раза, не выведя его прямо в исходный код. Я просто хочу ссылаться на этот динамический образ, а не на его перепечатку. Я думал о том, чтобы сделать это по-своему, но, похоже, много работы по изменению размера и перерисовке всех изображений, когда они одинаковы. С его повторением я мог обойтись. –

+0

@Coin_op вы всегда можете сгенерировать массив с элементами изображения, которые src поступает из data-uri, а затем установить изображение как фон – K3N

+0

Upvote для использования холста html5 в качестве скоростного хранилища. И чтобы успокоить @Coin_op, холст очень эффективен при быстрых обновлениях/обновлениях и полностью поддерживается IE> 8 (pre-IE9 имеет только долю в процентах от браузера, и большая часть этой небольшой доли находится в Китае). – markE

Смежные вопросы