Как сделать, чтобы SVG анимация продолжалась с того же места, где и закончилась

Есть анимация вращения палки по кругу.
Она запускается по наведению мыши и прекращает вращаться по убиранию мыши с изображения.
Мне надо сделать так, что бы при повторном наведении анимация продолжалась с того же места где и закончилась при прекращении.

По идее за это должна отвечать accumulate="sum" но что-то не помогает.

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="170px" height="170px" viewBox="-50 -50 100 100" version="1.1">
 <circle r="22" fill="orange" />
 <line x1="0" y1="-40" x2="0" y2="40" stroke="red" stroke-width="6" />
<animateTransform attributeName="transform" begin="svg1.mouseenter" end="svg1.mouseleave" type="rotate"
                repeatCount="indefinite" restart="never  " dur="10s" from="0" to="360" accumulate="sum" fill="freeze" /> 
</svg>

PS: Надо сделать без JavaScript, либо указать что это невозможно без него.


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

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

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

Поэтому решение задачи по остановке и запуске анимации с того же места можно решить только с помощью JS

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="svg1"  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="170px" height="170px" viewBox="-50 -50 100 120" version="1.1" style="border: 1px solid;">
 <circle r="22" fill="orange" /> 
 <circle r="40" fill="none" stroke="purple" stroke-dasharray="1.93 19" stroke-dashoffset="1.19" stroke-width="8" />
 
 <line x1="0" y1="-40" x2="0" y2="40" stroke="red" stroke-width="6" >
 <animateTransform attributeName="transform" type="rotate" begin="svg1.click" repeatCount="indefinite"  dur="10s" from="0 0 0" to="360 0 0"  restart="whenNotActive" /> 
  </line>
 <g id="gO1" onclick='start()'>
        <circle cx="-30" cy="50"  r="6" fill="green" stroke="black" />
        <text x="-42" y="67" font-size="12" fill="green">Start</text>
      </g>
      <g  onclick='pause()'>
        <circle cx="30" cy="50"  r="6" fill="red" stroke="black" />
        <text x="20" y="67" font-size="12" fill="red">Stop</text>
      </g>
    </g>
</svg>

<script>
 var flag = 0,
    svg = document.querySelector('svg'),
    $svg = $(svg);

// Необходимо поймать второй клик (если на первом удалить атрибуты, анимация не начнётся), потом подменяем функцию на вызов по "разморозке" анимации
var start = function(){
  if(flag === 1){
    // Убираем у animateTransform триггер, чтобы не сбрасывалась анимация на ноль
    $svg.find('animateTransform').removeAttr('begin');
    
    start = function() {
      svg.unpauseAnimations()
    };
     start();
  }
  flag++;
}
var pause = function(){
  svg.pauseAnimations();
}
   </script>

Вариант с наведением на кнопки

Используется событие onmouseover

<g id="gO1" onmouseover='start()'>
<g id="stop" onmouseover='pause()'>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="svg1"  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="170px" height="170px" viewBox="-50 -50 100 120" version="1.1" style="border: 1px solid;">
 <circle r="22" fill="orange" /> 
 <circle r="40" fill="none" stroke="purple" stroke-dasharray="1.93 19" stroke-dashoffset="1.19" stroke-width="8" />
 
 <line x1="0" y1="-40" x2="0" y2="40" stroke="red" stroke-width="6" >
 <animateTransform attributeName="transform" type="rotate" begin="svg1.mouseover" repeatCount="indefinite"  dur="10s" from="0 0 0" to="360 0 0"  restart="whenNotActive" /> 
  </line>
 <g id="start" onmouseover='start()'>
        <circle cx="-30" cy="50"  r="6" fill="green" stroke="black" />
        <text x="-42" y="67" font-size="12" fill="green">Start</text>
      </g>
      <g id="stop"  onmouseover='pause()'>
        <circle cx="30" cy="50"  r="6" fill="red" stroke="black" />
        <text x="20" y="67" font-size="12" fill="red">Stop</text>
      </g>
    </g>
</svg>

<script>
 var flag = 0,
    svg = document.querySelector('svg'),
    $svg = $(svg);

// Необходимо поймать второй клик (если на первом удалить атрибуты, анимация не начнётся), потом подменяем функцию на вызов по "разморозке" анимации
var start = function(){
  if(flag === 1){
    // Убираем у animateTransform триггер, чтобы не сбрасывалась анимация на ноль
    $svg.find('animateTransform').removeAttr('begin');
    
    start = function() {
      svg.unpauseAnimations()
    };
     start();
  }
  flag++;
}
var pause = function(){
  svg.pauseAnimations();
}
   </script>
   

Скрипт был взят из этого ответа

→ Ссылка
Автор решения: Дмитрий Полянин

Получилось решить задачу средстваами чистого CSS

#svg1:hover {
  animation-play-state: running;
}

#svg1 {
  animation-duration: 8s;
  animation-name: rot1;
  animation-fill-mode: forwards;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-play-state: paused;
}

@keyframes rot1 {
  to {
    transform: rotate(360deg);
  }
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="170px" height="170px" viewBox="-50 -50 100 100" version="1.1">
 <circle r="22" fill="orange" />
 <line x1="0" y1="-40" x2="0" y2="40" stroke="red" stroke-width="6" />
</svg>

Идея ответа взята здесь.

→ Ссылка