#javascript #html #svg
#javascript #HTML #svg
Вопрос:
У меня есть элемент SVG, и я динамически с помощью JavaScript создаю элемент Circle с элементом animateMotion. Круг должен динамически следовать вместе с путем SVG. Я подключаю прослушиватель endEvent к элементу animateMotion, поэтому после завершения анимации созданный элемент Circle должен быть удален из DOM, и весь процесс должен начаться снова. Он отлично работает для первой анимации, но не для других итераций. Код ниже — где я допустил ошибку?
const test = document.getElementById('test');
function createAnimation() {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
const animation = document.createElementNS('http://www.w3.org/2000/svg', 'animateMotion');
circle.setAttributeNS(null, 'r', '8');
circle.setAttributeNS(null, 'fill', '#00F');
animation.setAttributeNS(null, 'dur', '2s');
animation.setAttributeNS(null, 'path', "M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z");
circle.appendChild(animation);
test.appendChild(circle);
animation.addEventListener('endEvent', () => {
circle.parentElement.removeChild(circle);
});
return new Promise((resolve) => {
animation.addEventListener('endEvent', () => {
resolve();
});
});
}
(async() => {
while (true) {
await createAnimation();
}
})();
<svg id="test" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="lightgrey"
d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
</svg>
Ответ №1:
Анимации SMIL основаны на глобальных часах. По умолчанию, если вы не укажете a begin
, анимация начнется в момент времени 0. Где время 0 — это время создания / отображения документа.
После первого прогона анимации (длительность = 2 секунды) глобальные временные часы будут равны 2 секундам.
В этот момент вы добавляете новый круг и <animateMotion>
элемент. Его время начала также по умолчанию равно «0». Это означает, что браузер считает, что период выполнения для этой анимации был и прошел. Это потому, что мы уже прошли отметку в 2 секунды.
Попробуйте следующее:
- Добавить
begin="indefinite"
к анимации. Это сообщает браузеру, что вы намерены запустить анимацию самостоятельно.animation.setAttribute('begin', 'indefinite');
- Запустите анимацию после того, как вы закончите ее создание.
animation.beginElement();
Однако…
Зачем продолжать создавать все больше и больше кругов? Есть ли причина для этого? Почему бы просто не перезапустить анимацию, когда она будет завершена? Что-то вроде
createAnimation();
animation.addEventListener('endEvent', () => {
animation.beginElement();
});