Можно ли оптимизировать js-код для запуска и реверса smil-анимации при клике на svg-иконки когда их несколько?

Помогите, пожалуйста, разобраться, можно ли как-то оптимизировать js-код для реализации функционала запуска по клику вложенной smil-анимации svg-иконок и реверсивной анимации при следующем клике — в условиях, когда иконок на странице много, и в перспективе могут добавляться новые?

(При этом: — используются inline svg, которые стилизуются через переменные; — при необходимости все кнопки с svg-иконкой могут иметь как минимум один общий класс)

В найденном здесь решении для запуска\реверса анимации одиночной svg-иконки по клику смущает необходимость дублирования всего этого js-кода для каждой отдельной иконки и, соответственно, необходимость в каждом случае создания уникальных id. Есть ли варианты для более правильного\универсального\изящного решения?

(Например, можно ли как-то для всех svg-иконок с определенным классом (например, .button_svg) на странице иметь один общий js-код для реализации вложенной интерактивной анимации по кликам? (Например, если для значений < animate > задавать не уникальные id, а унифицированные классы (либо типизированные id, например "buttonsvg_start_1", "buttonsvg_start_2")?)

Вот пример с дублированием js-логики на примере анимации двух иконок - бургер-меню и иконки поиска (лупы). Для удобства в каждом случае я положил js-код в < defs >:

.wrapper {
 width: 3rem;
 height: 3rem;
 margin: 3rem;
}

.button_icon {
  cursor: pointer;
}

.animate_icon {
  stroke: black;
  stroke-width: 12;
  stroke-miterlimit: 12; 
  stroke-linecap: round;
  stroke-linejoin: round; 
}
<div class="wrapper">
<div class="button_icon">
<svg version="1.1" id="iconburger" class="animate_icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 128 128" overflow="visible" xml:space="preserve">   
 <defs>
  <script>
   var iconburger = document.getElementById("iconburger"),
    close = document.getElementById("iconburgerClose"),
    open = document.getElementById("iconburgerOpen");

    let iconburgerFlag = true;

    iconburger.addEventListener('click', function() {
     if (iconburgerFlag == true) {
      iconburgerClose.beginElement();
      iconburgerFlag = false;
     } else {
      iconburgerOpen.beginElement();
      iconburgerFlag = true;
     }
    });
  </script>
 </defs> 
 
 <path id="iconburger-active" d="M 0 4 L 64 4 M 0 64 L 128 64 M 0 124 L 96 124" stroke="black" stroke-width="8" stroke-linecap="round" >
  <animate id="iconburgerClose" begin="indefinite" fill="freeze" attributeName="d" dur="0.2s" to="M 4 4 L 64 64 M 4 124 L 124 4 M 64 64 L 124 124"/>
  <animate id="iconburgerOpen" begin="indefinite" fill="freeze" attributeName="d" dur="0.2s" to="M 0 4 L 64 4 M 0 64 L 128 64 M 0 124 L 96 124"/>
 </path>
</svg>
</div>
</div>

<div class="wrapper">
<div class="button_icon">
<svg version="1.1" id="iconsearch" class="animate_icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 128 128" overflow="visible" xml:space="preserve">   
 <defs>
  <script>
   var iconsearch = document.getElementById("iconsearch"),
    close = document.getElementById("iconsearchClose"),
    open = document.getElementById("iconsearchOpen");

    let iconsearchFlag = true;

    iconsearch.addEventListener('click', function() {
     if (iconsearchFlag == true) {
      iconsearchClose.beginElement();
      iconsearchFlag = false;
     } else {
      iconsearchOpen.beginElement();
      iconsearchFlag = true;
     }
    });
  </script>
 </defs> 
 
 <path id="iconsearch-active" d="M 18.398 18.398 C 11.743 25.053 8 34.088 8 43.5 C 8 52.912 11.743 61.947 18.398 68.602 C 25.053 75.257 34.088 79 43.5 79 C 52.912 79 61.947 75.257 68.602 68.602 C 75.257 61.947 79 52.912 79 43.5 C 79 34.088 75.257 25.053 68.602 18.398 C 61.947 11.743 52.912 8 43.5 8 C 34.088 8 25.053 11.743 18.398 18.398 M 124 124 L 70 70" fill="none" stroke="black" stroke-width="8" stroke-linecap="round" >
  <animate id="iconsearchClose" begin="indefinite" fill="freeze" attributeName="d" dur="0.2s" to="M 18.398 18.398 C 11.743 25.053 8 34.088 8 43.5 C 8 52.912 11.743 61.947 18.398 68.602 C 25.053 75.257 34.088 79 43.5 79 C 52.912 79 61.947 75.257 68.602 68.602 C 75.257 61.947 79 52.912 79 43.5 C 79 34.088 75.257 25.053 68.602 18.398 C 61.947 11.743 52.912 8 43.5 8 C 34.088 8 25.053 11.743 18.398 18.398 M 124 124 L 70 70"/>
  <animate id="iconsearchOpen" begin="indefinite" fill="freeze" attributeName="d" dur="0.2s" to="M 4 124 C 8.333 119.667 12.667 115.333 17 111 C 22.333 105.667 27.667 100.333 33 95 C 38.333 89.667 43.667 84.333 49 79 C 54 74 59 69 64 64 C 69.333 58.667 74.667 53.333 80 48 C 85.333 42.667 90.667 37.333 96 32 C 101.333 26.667 106.667 21.333 112 16 C 116 12 120 8 124 4 M 124 124 L 4 4"/>
 </path>
</svg>
</div>
</div>

P. S. Прошу прощения, если вопрос некорректный или глупый, либо оформлен неверно — это первое мое обращение на stackoverflow, перед этим я добросовестно перелопатил десятки страниц по соответствeющим моей задаче запросам, документацию по smil-анимации etc., и я пока только начинаю осваивать js. Заранее спасибо, если кто-то сможет помочь мне и подскажет хороший паттерн реализации такой интерактивности.


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

Автор решения: Маргарита Андрианова
const svg_icons = document.getElementsByClassName("animate_icon");

for (let i = 0; i < svg_icons.length; i++) {
  let icon = svg_icons[i]
  let flag = true
  // https://developer.mozilla.org/ru/docs/Web/API/Document/querySelector <animate class="open"></animate>
  let open = icon.querySelector("animate.open")
  let close = icon.querySelector("animate.close")
  icon.addEventListener("click", () => {
    if (flag) {
      open.beginElement()
      flag = false
    } else {
      close.beginElement()
      flag = true
    }
    

  })
}
→ Ссылка