Как сделать, чтобы 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 шт):
У 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>
Идея ответа взята здесь.