Как вернуть анимацию SVG в исходное состояние?

У меня есть SVG-анимация, подобная этой:

function startAnimation() {
  document.querySelector('#anim-width').beginElement();
}
<svg width="100" viewBox="0 0 100 100">
  <rect id="box" x="10" y="10" fill="red" width="10" height="10">
    <animate
      id="anim-width"
      attributeName="width"
      from="10"
      to="80"
      dur="1s"
      fill="freeze"
      begin="click"
    />
    
    <animate
      attributeName="height"
      from="10"
      to="80"
      begin="anim-width.end + 0s"
      dur="1s"
      fill="freeze"
    />
  </rect>
</svg>

<br/>

<button onclick="startAnimation()">Start</button>

Я хочу добиться, чтобы красный прямоугольник начинался с размера 10 на 10, и при нажатии кнопки его ширина увеличивается с 10 до 80, а затем height увеличивается до 80 после завершения анимации ширины.

Это отлично работает при первом воспроизведении, но при повторном нажатии кнопки высота начинается с 80 вместо 10. Как мне сбросить все до исходного состояния и воспроизвести всю анимацию?

Я пробовал добавить document.querySelector('# box').SetAttribute('height', '10'); в функции startAnimation()`, но, похоже, это не работает.

Свободный перевод вопроса How to reset an svg animation to its initial state? от участника @Hao Wu.


Ответы (2 шт):

Автор решения: Alexandr_TT

Я добавляю элемент <set> внутри прямоугольника и запускаю элемент set внутри функции startAnimation()

Элемент <set> позволяет установить значение атрибута (в данном случае высоту), как анимация с длительностью 0.

function startAnimation() {
  document.querySelector("#set").beginElement();
  document.querySelector("#anim-width").beginElement();
}
<svg width="100" viewBox="0 0 100 100">
  <rect id="box" x="10" y="10" fill="red" width="10" height="10">
    <animate id="anim-width" attributeName="width" from="10" to="80" dur="1s" fill="freeze" begin="click" />

    <animate id="anim-height" attributeName="height" from="10" to="80" begin="anim-width.end + 0s" dur="1s" fill="freeze" />

    <set id="set" attributeName="height" to="10"></set>
  </rect>
</svg>

<br />

<button onclick="startAnimation()">Start</button>

Свободный перевод ответа от участника @enxaneta.

→ Ссылка
Автор решения: Alexandr_TT

Другой вариант - просто использовать элемент <animate>, который запускает анимацию, сбрасывая высоту.

document.querySelector("#anim-height").addEventListener("endEvent", enableButton);

function startAnimation() {
  document.querySelector("#start-btn").disabled = true;
  document.querySelector("#anim-start").beginElement();
}


function enableButton()
{
  document.querySelector("#start-btn").disabled = false;
}
<svg width="100" viewBox="0 0 100 100">
  <rect id="box" x="10" y="10" fill="red" width="10" height="10">
    <animate id="anim-start" attributeName="height" to="10" dur="0.01s" fill="freeze" begin="indefinite" />
    <animate id="anim-width" attributeName="width" from="10" to="80" dur="1s" fill="freeze" begin="anim-start.end + 0s" />
    <animate id="anim-height" attributeName="height" from="10" to="80" begin="anim-width.end + 0s" dur="1s" fill="freeze" />
  </rect>
</svg>

<br />

<button id="start-btn" onclick="startAnimation()">Start</button>

Свободный перевод ответа от участника @Paul LeBeau.

→ Ссылка