Pull to refresh

Comments 20

У канваса логика отрисовки построена на перерисовке всей карты.

Это проблема конкретной вашей реализации, а не самого канваса.
В канвасе можно перерисовать отдельный фрагмент. Но перерисованный фрагмент наложится на изображение. Можно стереть часть изображения перед наложением фрагмента, но тогда появится пустые области. Кроме того, довольно сложно каждый раз вычислить область наложения особенно при выводе текста несколько раз в одной области. Поэтому я имел в виду перерисовку всей картинки как базовый вариант работы с канвасом в динамике.
Кроме того, довольно сложно каждый раз вычислить область наложения особенно при выводе текста несколько раз в одной области.

Ну, если правильная архитектура приложения, то ничего сложного нет.
При создании игр все эти проблемы давно давным решили…
Дам совет — лучше карту рисовать в буфер и скролиннг реализовывать уже по этому буферу, а не рисовать каждый раз, с отключением текста. :)
Мне бы собраться с мыслями и про Вангеры написать (там к слову этот подход во всю, каждый объект сам за собой чистил).
Первые 3 «во-первых» легко решаются библиотеками для canvas.
Какими, например? И как? У каждой библиотеки своя область применения.
Ну это естественно.
LibCanvas, Fabric, Graphics2D, PaperJS хотя бы. Первое, что вспомнилось.
Они общего назначения, есть и специализированные.

Во-первых, потребовалось меньшее количество кода для создания на svg.

Сравниваем:
<rect x="10" y="10" width="200" height="200" fill="red"/>
<path d="M10,10 L200,200 L400,10" fill="blue"/>

Пример для canvas будет на Graphics2d, т.к. я её лучше всего знаю, да и там короче всех, пожалуй:
var rect = ctx.rect(10, 10, 200, 200, 'red');
// либо:
var rect = ctx.rect({ x: 10, y: 10, width: 200, height: 200, fill: 'red' });

var path = ctx.path([[10, 10], [200, 200], [400, 10]], 'blue');

А многие библиотеки (Fabric, например) и SVG-пути поддерживают.

Во-вторых, простота и удобство создания кода. У svg логика строится на отдельных объектах, их свойствах и методах. Например, чтобы определить объект под курсором, нужно создать обработчик события для данного объекта (circle для станций метро), в котором можно поменять его свойства — цвет, масштаб (на картинке для значка станции «Ходынское поле» применен метод scale) и др. У канваса логика отрисовки построена на перерисовке всей карты. И для выделения отдельных объектов нужно перерисовывать и масштабировать всю карту. Кроме этого, канвас не хранит отрисованные объекты в памяти, их нужно отдельно сохранять в переменных (в dbcartajs в объекте mflood) и самому следить за ними (добавлять, удалять). SVG-изображение хранит отрисованные объекты в DOM-модели и к ним можно обращаться напрямую.

Та-даам.
var station = ctx.circle({ cx: 50, cy: 50, radius: 10, fill: 'red', stroke: 'red 2px' });
station.on('mouseover', 'animate', 'stroke', 'blue', 1000);
station.on('mouseout', 'animate', 'stroke', 'red', 1000);

Вот так ещё можно:
station.on('mouseover', function(e){
  this.animate('stroke', 'blue', 1000);
  this.scale(1.3);
});

station.on('mouseout', function(e){
  this.animate({
    stroke: 'blue',
    scale: 1 / 1.3
  }, 1000);
});


В общем-то, на всех 4-х из мною перечисленных это спокойно реализуется.
Ах да, и забыл:
В-третьих, возможностей в svg намного больше, чем в канвасе, например, анимация, фильтры для изображений.

Анимацию в G2D я уже показал, в LibCanvas тоже есть, и в Fabric.
Фильтры в Fabric:
fabric.Image.fromURL('image.jpg', function(img) {
  img.filters.push(new fabric.Image.filters.Grayscale());
  img.applyFilters(canvas.renderAll.bind(canvas));
  canvas.add(img);
});

Фильтры в g2d:
var image = ctx.image('image.jpg', 10, 10);
image.filter('pixel', function(r, g, b){
 var mid = (r + g + b) / 3;
 return [mid, mid, mid, 1];
});

Тут пример с Grayscale, встроенных в G2D пока нет.

Да и вообще реализовать, в общем-то, несложно, в отличие от SVG есть прямой доступ к пикселям.
Приятно получить комментарий тоже от разработчика библиотеки для канваса. Только почему ни один пример не работает на http://graphics2d.js.org? Хотелось бы увидеть что-нибудь из вышеописанного в действии. В проекте graphics2d примеров тоже нет.
Всё пофиксил, благодарю. Добавил ещё один пример, теперь можно оценить соотношение прыгающих зайчиков и FPS :).

Сейчас очень многое изменяю, хочется сделать более общей и более функциональной (а ещё добавить WebGL-рендер), поэтому последние версии немного неюзабельны, а на сайте многое немного не работает. Думаю, к ноябрю закончу.
А ещё SVG автоматически адаптирует своё качество в зависимости от плотности точек дисплея (например, на 4K-мониторе с системным масштабом 200%). Векторная графика есть векторная графика.
Для канвы это тоже делается на раз-два, см. функцию getRetinaRatio здесь.
Ну да, можно выводить растровое изображение пропорционально бОльших размеров, вписывая его в пропорционально меньшую область (и надеясь на точное попадание каждого логического пиксела в пиксел физический — для нештриховой графики сейчас так и приходится делать), но зачем, если можно просто использовать векторную графику, именно для штриховых изображений подходящую идеально и адаптирующуюся под любую плотность точек автоматически и с гарантированным качеством? (Вопрос риторический.)
UFO just landed and posted this here
Да действительно, я уже и забыл, что в последних версиях канвасной карты метро я заменил отрисовку линий по координатам на фоновую картинку-скриншот с линиями. Отрисовываются только точки (прямоугольники) станций. Загружаться карта стала немного медленнее чем раньше (до v1.8). Зато намного быстрее стала работать на смартфоне особенно при перетаскивании и масштабировании. А SVG и правда быстрее.
А можете дополнить карту дополнительными элементами — ССВ и депо? Например отсюда — trackmap.ru
Все можно. А почему бы самому не попробовать? На заказ я уже делал одну карту в своем блоге, но товарищ после этого почему-то прекратил переписку.
Sign up to leave a comment.

Articles