#svg #svg-animate
#svg #svg-анимировать
Вопрос:
Перо: https://codepen.io/jkmg/pen/zYKqvLq
<html>
<head>
<title></title>
<style type="text/css">
html,body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
background-color: purple;
}
svg {
height: 50px;
}
.playButton {
width: 100px;
height: 100px;
background-color: white;
display: inline-flex;
position: fixed;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -50px;
border-radius: 200px;
overflow: hidden;
}
.playButton .poscont {
position: absolute;
width: 100px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.playButton .playGlyph {
opacity: 1;
margin-right: -5px;
}
</style>
</head>
<body>
<span></span>
<div class="playButton currentlyPaused">
<div class="playGlyphPosition poscont">
<svg class="playGlyph One" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.83 122.58">
<path id="playPath" d="M20.55,119.08a11.89,11.89,0,0,1-20.3-8.35L0,61.29.25,11.85a11.89,11.89,0,0,1,20.3-8.34l45,45a18.11,18.11,0,0,1,0,25.62Z">
<animate xlink:href="#playPath"
begin="indefinite"
id="pauseAni"
attributeName="d"
dur="1s"
fill="freeze"
attributeType="XML"
from="M20.55,119.08a11.89,11.89,0,0,1-20.3-8.35L0,61.29.25,11.85a11.89,11.89,0,0,1,20.3-8.34l45,45a18.11,18.11,0,0,1,0,25.62Z"
to="M20.55,109.49c0,15-20.3,15-20.3-.06L0,60,.25,10.55c0-14.06,20.3-14.06,20.3-.06l0,36.69c.31,7.31.31,16.31,0,25.62Z"
/>
</path>
</svg>
</div>
</div>
<script type="text/javascript">
document.querySelector(".playButton").addEventListener("click", function () {
if (this.classList.contains("currentlyPaused")) {
this.classList.remove("currentlyPaused");
this.classList.add("currentlyPlaying");
document.querySelector("#pauseAni").beginElement();
document.querySelector("span").innerText = "nAttempted to play, ani to pause.";
}
else {
this.classList.remove("currentlyPlaying");
this.classList.add("currentlyPaused");
// document.querySelector("#playAni").beginElement();
// this.querySelector(".playGlyph").classList.add("playing");
document.querySelector("span").innerText = "nAttempted to pause, ani to play.";
}
});
</script>
</body>
</html>
Я пытаюсь анимировать кнопку воспроизведения на кнопку паузы и преобразовать кнопку воспроизведения в искусственную строку для использования в качестве элемента для кнопки паузы.
Я понятия не имею, почему анимация, анимируемая с помощью CSS или нет, переходит к концу анимации, фактически не «анимируя». Может кто-нибудь, пожалуйста, помочь мне разобраться, что происходит?
Комментарии:
1. Если вы хотите, чтобы анимация была плавной, пути from и to должны содержать одинаковые команды. У вас этого нет. В одном вторая команда — a, в другом — c
2. Готовый продукт для тех, кто хочет знать, как это получилось: https://codepen.io/jkmg/pen/zYKqvLq
Ответ №1:
Я понятия не имею, почему анимация, анимация с помощью CSS или нет, переходит к концу анимации без фактического «анимации». Может кто-нибудь, пожалуйста, помочь мне разобраться, что происходит?
Как прокомментировал @Robert Longson и как показано в ответе @Paul LeBeau«, причина не гладкой анимации связана с отсутствием требований:
- Количество узловых точек в начальной
path
и в конечнойpath
должны быть одинаковыми. Это требование выполнено. - Тип узлов должен быть одинаковым в одинаковых позициях в обоих путях
Это требование не выполнено
Чтобы выполнить эти требования к начальному и конечному контуру, вы можете использовать технику редактирования в векторном редакторе.
Начальный путь
Конечный путь
Остается скопировать эти исправления из векторного редактора и добавить их в свой код.
Я заменил код вашего скрипта. Вероятно, вы можете использовать любой скрипт, который выполняет триггерные функции.
var svg_1 = document.getElementById("svg1"),
pause = document.getElementById("pause"),
play = document.getElementById("play");
let flag = true;
svg_1.addEventListener('click', function() {
if (flag == true) {
pause.beginElement();
flag = false;
} else {
play.beginElement();
flag = true;
}
});
<html>
<head>
<title></title>
<style type="text/css">
html,body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
background-color: purple;
}
svg {
height: 50px;
}
.playButton {
width: 100px;
height: 100px;
background-color: white;
display: inline-flex;
position: fixed;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -50px;
border-radius: 200px;
overflow: hidden;
}
.playButton .poscont {
position: absolute;
width: 100px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.playButton .playGlyph {
opacity: 1;
margin-right: -5px;
pointer-events:all;
}
</style>
<div class="playButton currentlyPaused">
<div class="playGlyphPosition poscont">
<svg id="svg1" class="playGlyph One" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.83 122.58">
<path d="m20.6 119.1c-5 5.3-20.3 2.2-20.3-8.3L0 61.3 0.3 11.9C0.3 1.3 15.4-1.2 20.6 3.5 26.3 8.8 29.4 12.3 35.8 18.9 43.7 26.9 50.8 35.1 58.7 42.7 73.9 57.3 74.6 64.7 59.1 80.7 52.6 87.5 46.5 92.5 36.1 103 29.2 110.1 27.5 111.8 20.6 119.1Z" style="fill:black;stroke:#000">
<animate id="play" attributeName="d" dur="0.2s" begin="indefinite" fill="freeze" attributeType="XML"
to="m20.6 119.1c-5 5.3-20.3 2.2-20.3-8.3L0 61.3 0.3 11.9C0.3 1.3 15.4-1.2 20.6 3.5 26.3 8.8 29.4 12.3 35.8 18.9 43.7 26.9 50.8 35.1 58.7 42.7 73.9 57.3 74.6 64.7 59.1 80.7 52.6 87.5 46.5 92.5 36.1 103 29.2 110.1 27.5 111.8 20.6 119.1Z" />
<animate id="pause" attributeName="d" dur="0.2s" begin="indefinite" fill="freeze" attributeType="XML"
to="M20.6 111C20.5 125.5 0.3 125.7 0.3 110.7L0 61.3 0.3 17c0-21.4 20.2-20.6 20.2-0.1 0 6.4 0 10 0 12.8 0 11.8 0.2 7.5 0.2 13-0.2 21.6-0.2 15.4 0 38.1 0.1 9.3 0.1 18.9 0 22.6-0.1 4.3-0.1 3.3-0.1 7.5z"/>
</path>
</svg>
</div>
</div>
Ответ №2:
Я расширю комментарий Роберта.
Для анимации два значения общего свойства могут быть плавно интерполированы только тогда, когда строки данных пути содержат одинаковую структуру (т. Е. Точно такое же количество и типы команд данных пути, которые находятся в том же порядке). Если задана анимация и списки команд данных пути не имеют одинаковой структуры, то значения должны быть интерполированы с использованием дискретного типа анимации.
Однако ваши два пути не имеют одинаковой структуры. Первый путь:
M 20.55,119.08
a 11.89,11.89,0,0,1-20.3-8.35
L 0,61.29.25,11.85
a 11.89,11.89,0,0,1,20.3-8.34
l 45,45
a 18.11,18.11,0,0,1,0,25.62
Z
и второй:
M 20.55,109.49
c 0,15-20,3,15-20.3-.06L0,60,.25,10.55
c 0-14.06,20.3-14.06,20.3-. 06l0,36,69
c .31,7.31.31,16.31,0,25.62
Z
Если вы хотите выполнить интерполяцию между двумя путями, они должны иметь одинаковое количество и тип команд пути.
Другими словами, вам нужно отредактировать один (или оба), чтобы они соответствовали.
Комментарии:
1. Для дальнейшего решения, исправит ли проблему изменение структуры пути для соответствия путем простого редактирования начальной переменной каждой точки?
2. Если вы имеете в виду буквы команд (M, a, L, c и т.д.), То нет. Команды означают разные вещи. M — перемещение, L — линия, a — дуга. Вам нужно будет отредактировать эти пути в векторном редакторе, таком как Inkscape. Определите, какие типы сегментов вам понадобятся (возможно, какая-то комбинация M, L и C) и сколько их. Начните с одной фигуры. Затем отрегулируйте точки, чтобы сформировать вторую фигуру, не добавляя и не удаляя какие-либо,
3. Спасибо! Я смог достичь желаемого результата и продвинуться вперед с анимацией. Спасибо за вашу помощь. Это было большим подспорьем в определении того, с какой точкой я имел дело: ссылка После того, как я смог сопоставить команды в более идеальном месте, я закончил тем, что изменил тип анимации на сплайн, чтобы получить более контролируемый эффект простоты. Еще раз спасибо!