Как нарисовать векторный путь постепенно? (Raphaël.js)
Как оживить векторный путь, как его рисование, постепенно? Другими словами, медленно покажите пиксель пути по пикселям.
Я использую Raphaël.js
, но если ваш ответ не является специфичным для библиотеки - например, может быть, существует какой-то общий шаблон программирования для такого рода вещей (я довольно новичок в векторной анимации) - приветствую!
Это легко сделать с прямыми дорожками, так же просто, как пример на что страница::
path("M114 253").animate({path: "M114 253 L 234 253"});
Но попробуйте изменить код на этой странице, скажем так:
path("M114 26").animate({path: "M114 26 C 24 23 234 253 234 253"});
И вы поймете, что я имею в виду. Путь, конечно, анимирован из его начального состояния (точка "M114 26" ) до конечного состояния (кривая "C 24 23 234 253 234 253", начиная с точки "M114 26" ), но не так, как указано в вопросе, а не как он рисуется.
Я не вижу, как это может сделать animateAlong
. Он может анимировать объект вдоль пути, но как я могу сделать этот путь, чтобы постепенно проявлять себя, когда объект анимируется вдоль него?
Решение?
(Via ответ peteorpeter.)
Кажется, что в настоящее время лучший способ сделать это - через "поддельные" тире с использованием необработанного SVG. Для объяснения см. это демо или этот документ, страница 4.
Как произвести прогрессивный чертеж?
Мы должны использовать stroke-dasharray
и stroke-dashoffset
и знать длину кривой для рисования. Этот код ничего не рисует на экране для круга, эллипса, полилинии, полигона или пути:
<[element] style="stroke-dasharray:[curve_length],[curve_length]; stroke-dashoffset:[curve_length]"/>
Если в анимированном элементе stroke-dashoffset уменьшается до 0, мы получаем прогрессивный рисунок кривой.
<circle cx="200" cy="200" r="115"
style="fill:none; stroke:blue; stroke-dasharray:723,723; stroke-dashoffset:723">
<animate begin="0" attributeName="stroke-dashoffset"
from="723" to="0" dur="5s" fill="freeze"/>
</circle>
Если вы знаете лучший способ, оставьте ответ.
Обновить (26 апреля 2012 г.): нашел пример, который хорошо иллюстрирует идею, см. Анимированные кривые Безье.
Ответы
Ответ 1
Я создал script для этого: Scribble.js, основанный на этом отличном dasharray/dashoffset
.
Просто создайте экземпляр этой строки SVG <path>
s:
var scribble = new Scribble(paths, {duration: 3000});
scribble.erase();
scribble.draw(function () {
// done
});
-
NB: Полный USAGE
код здесь: https://gist.github.com/abernier/e082a201b0865de1a41f#file-index-html-L31
Наслаждайтесь;)
Ответ 2
Возможно, кто-то ищет ответ, как я, в течение двух дней:
// Draw a path and hide it:
var root = paper.path('M0 50L30 50Q100 100 50 50').hide();
var length = root.getTotalLength();
// Setup your animation (in my case jQuery):
element.animate({ 'to': 1 }, {
duration: 500,
step: function(pos, fx) {
var offset = length * fx.pos;
var subpath = root.getSubpath(0, offset);
paper.clear();
paper.path(subpath);
}
});
Это помогло мне, только используя методы RaphaelJS.
Вот пример jsFiddle, запрошенный в комментариях, http://jsfiddle.net/eA8bj/
Ответ 3
Эврика! (Может быть, если вы согласитесь, что вам удобно выйти за пределы дружественного царства Рафаэля в чистую землю SVG...)
Вы можете использовать SVG keyTimes и keySplines.
Вот рабочий пример:
http://www.carto.net/svg/samples/animated_bustrack.shtml
... и вот какое-то потенциально полезное объяснение:
http://msdn.microsoft.com/en-us/library/ms533119(v=vs.85).aspx
Ответ 4
Я хотел бы предложить альтернативу, решение Raphael + JS, которое я использовал в своей работе. Он имеет несколько преимуществ по сравнению с решением давиденке:
- Не очищает бумагу с каждым циклом, позволяя анимированному пути хорошо сосуществовать с другими элементами;
- Повторное использование одного пути с собственной прогрессивной анимацией Raphael, создающей более плавные анимации;
- Значительно менее ресурсоемкий.
Здесь метод (который можно легко переопределить в расширение):
function drawpath( canvas, pathstr, duration, attr, callback )
{
var guide_path = canvas.path( pathstr ).attr( { stroke: "none", fill: "none" } );
var path = canvas.path( guide_path.getSubpath( 0, 1 ) ).attr( attr );
var total_length = guide_path.getTotalLength( guide_path );
var last_point = guide_path.getPointAtLength( 0 );
var start_time = new Date().getTime();
var interval_length = 50;
var result = path;
var interval_id = setInterval( function()
{
var elapsed_time = new Date().getTime() - start_time;
var this_length = elapsed_time / duration * total_length;
var subpathstr = guide_path.getSubpath( 0, this_length );
attr.path = subpathstr;
path.animate( attr, interval_length );
if ( elapsed_time >= duration )
{
clearInterval( interval_id );
if ( callback != undefined ) callback();
guide_path.remove();
}
}, interval_length );
return result;
}
И вот два примера его использования на моем сайте: один для Path Transformation, а другой для Прогрессивная надпись.
Ответ 5
Используя атрибут pathLength ", мы можем установить виртуальную длину пути. С этого момента мы можем использовать эту виртуальную длину в" stroke-dasharray".
Поэтому, если мы установим "pathLength" на 100 единиц, тогда мы можем установить "stroke-dasharray" на "50,50", который будет равен 50%, 50% пути!
Существует одна проблема с этим подходом: единственным браузером, поддерживающим этот атрибут, является Opera 11.
Здесь - пример плавной анимации рисования кривой без javascript или hardcoded length (работает правильно только в Opera 11)
Ответ 6
Решение Anton и Peteorpeter печально ломается в Chrome, когда пути усложняются. Это хорошо для карты автобусов в этой связанной демо. Проверьте эти анимированные "цветочные лепестки" jsfiddle, которые я создал, который правильно рисует в FF10 и Safari5, но неумело мерцает в Chrome:
http://jsfiddle.net/VjMvz/
(Это все HTML и встроенный SVG, не javascript.)
Я все еще ищу для этого решение, отличное от Flash. Очевидно, AnimateAlong не сократит его за то, что я делаю. Raphael.js может работать, хотя он грозит превратиться в спагетти обратного вызова очень быстро.
Дэвиденке, можете ли вы опубликовать рабочий файл с вашим решением? Я просто не могу заставить его работать. Я получаю ошибку в Chrome 18, что узлы, которые настроены на "display: none" с вашим ".hide", не имеют метода getTotalLength.
Ответ 7
К сожалению, как вы, кажется, согласны, вы, вероятно, не можете сделать это элегантно в Рафаэле.
Однако, если через некоторый штрих %deity%
вам не нужно поддерживать IE для этой конкретной функции, вы можете отказаться от API Raphael и манипулировать SVG напрямую. Тогда, возможно, вы могли бы установить mask, чтобы проехать по пути и показать линию в естественном темпе.
Вы можете грамотно деградировать в IE, чтобы просто показать путь с помощью Raphael без анимации.
Ответ 8
Я просто делал именно это. Первое, что я пробовал, - это решение Антона, но производительность отстой.
В конце концов, самый простой способ получить результат, который я хотел, - использовать альтернативный синтаксис "ключевого кадра" для функции animate.
нарисовать последний путь невидимо, затем сгенерировать целую кучу ключевых кадров, используя getSubpath в цикле.
создать новый путь, который будет виден и равен первому ключевому кадру.
тогда сделайте что-то вроде:
path.anmimate({keyFrameObject, timeframe});
вам не нужен ключевой кадр для каждого пикселя, который вы хотите рисовать. После игры с параметрами я обнаружил, что значение 100 пикселей на ключевой кадр работает для сложности/размера того, что я пытался "рисовать"
Ответ 9
Просто обновите это, вы можете попробовать Lazy Line Painter
Ответ 10
Вы пробовали Raphael animateAlong? Вы можете увидеть его в действии на демонстрационной странице.
Ответ 11
Хорошо, вот мои мысли об этом... Решение слишком далеко от идеала.
Чтобы постепенно показывать среднее значение пути, мы должны показать его, например, точками. И векторные пути состоят не из точек, а из кривых, поэтому мне кажется, что нет естественного способа постепенного рисования пути в векторной графике. (Хотя я довольно новичок в этом и могу ошибаться.)
Единственный способ - каким-то образом преобразовать путь к нескольким точкам и показать их один за другим.
В настоящее время мое обходное решение состоит в том, чтобы нарисовать путь, сделать его невидимым, разбить его на несколько подпапок и показать, что подпапки один за другим.
Это не сложно сделать с Рафаэлем, но это тоже не изящно, и довольно медленно на больших дорожках. Не принимаю мой ответ, надеясь, что там будет лучший способ...