Более быстрое манипулирование SVG Path

Итак, я хочу сделать инструмент для рисования с помощью SVG, я использую довольно наивный подход, чтобы изменить атрибут d моего пути:

$("div#drawarea").bind("mousemove", function(ev) {

  ev.preventDefault();

  ev.stopPropagation();

  var pX= (ev.pageX - this.offsetLeft);

  var pY= (ev.pageY - this.offsetTop);

  $path.attr("d", $path.attr("d") + " L" +pX+ "," + pY); //using jquery-svg here to change the d attribute

});

Как видите, я делаю это с помощью функции mousemove. Код работает, но перестает отвечать на запросы, когда мышь движется быстро, создавая множество прямых линий, тогда как я действительно хочу, чтобы они были плавными. Я думаю, что это происходит из-за многочисленных конкатенаций строк, которые я выполняю для события mousemove (атрибут d на пути может стать довольно большим, если щелчок удерживается долго, фактически тысячи символов).

Мне интересно, есть ли какой-либо собственный способ добавления новых значений в конце пути вместо того, чтобы напрямую манипулировать атрибутом d. Я проверил исходный код jquery-svg, и кажется, что библиотека также использует наивный режим конкатенации строк внутри, поэтому использование его методов не принесет никакой пользы.

Также мне интересно, так ли это, или браузер просто ограничивает количество событий mousemove (один раз каждые X миллисекунд?), которые могут быть запущены, и поэтому никакие оптимизации производительности не улучшат это.


person Hoffmann    schedule 20.08.2012    source источник
comment
Что вы можете сделать, так это заставить обработчик mousemove просто добавить точку в массив. Затем запустите другую подпрограмму, которая периодически обновляет SVG, например, раз в четверть секунды или около того, перестраивая атрибут d из массива точек.   -  person Pointy    schedule 20.08.2012
comment
@Pointy, который улучшит производительность, но является довольно уродливым способом сделать это (я придерживаюсь философии, согласно которой, если вам нужен таймер, чтобы что-то сделать в Javascript, вы должны переосмыслить то, как вы это делаете). Я подожду, чтобы узнать, получу ли я какой-либо другой ответ, если нет, я попробую по-вашему. Спасибо.   -  person Hoffmann    schedule 20.08.2012
comment
Проблема в том, что браузеры запускают много таких событий, и обновление DOM для каждого из них будет происходить медленно. Если вы не хотите использовать таймер опроса, вы можете проверить событие, чтобы увидеть, было ли запланировано обновление, и запланировать его нет. Затем код обновления SVG может очистить флаг после запуска.   -  person Pointy    schedule 20.08.2012


Ответы (2)


Используйте методы SVG pathseg DOM. Вам нужно написать более сложный код, но браузеру не нужно повторно анализировать весь атрибут пути. Например, Firefox использует это преимущество, и вполне вероятно, что и другие браузеры тоже.

person Robert Longson    schedule 20.08.2012
comment
Я просто хочу зайти и сказать, что хотя этот подход работал немного лучше, но в итоге я использовал тег canvas. - person Hoffmann; 31.08.2013

На случай, если кто-то еще наткнется на вопрос о том, как быстрее всего обновить атрибут данных SVG-Path (для приложений реального времени), я запускаю небольшой тест:

http://jsperf.com/svg-path-test

Да, установка его в виде строки означает, что его необходимо проанализировать, что не относится к интерфейсу DOM SVG, но первый метод все же намного быстрее. Может быть, интерфейс обновляет DOM с каждой добавленной точкой, замедляя весь процесс.

person stfn    schedule 29.01.2016