Анимация, переходящая в конец желаемого результата

#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>
 

gifforreference

Я пытаюсь анимировать кнопку воспроизведения на кнопку паузы и преобразовать кнопку воспроизведения в искусственную строку для использования в качестве элемента для кнопки паузы.

Я понятия не имею, почему анимация, анимируемая с помощью CSS или нет, переходит к концу анимации, фактически не «анимируя». Может кто-нибудь, пожалуйста, помочь мне разобраться, что происходит?

Комментарии:

1. Если вы хотите, чтобы анимация была плавной, пути from и to должны содержать одинаковые команды. У вас этого нет. В одном вторая команда — a, в другом — c

2. Готовый продукт для тех, кто хочет знать, как это получилось: https://codepen.io/jkmg/pen/zYKqvLq

Ответ №1:

Я понятия не имею, почему анимация, анимация с помощью CSS или нет, переходит к концу анимации без фактического «анимации». Может кто-нибудь, пожалуйста, помочь мне разобраться, что происходит?

Как прокомментировал @Robert Longson и как показано в ответе @Paul LeBeau«, причина не гладкой анимации связана с отсутствием требований:

  1. Количество узловых точек в начальной path и в конечной path должны быть одинаковыми. Это требование выполнено.
  2. Тип узлов должен быть одинаковым в одинаковых позициях в обоих путях

Это требование не выполнено

Чтобы выполнить эти требования к начальному и конечному контуру, вы можете использовать технику редактирования в векторном редакторе.

Начальный путь

введите описание изображения здесь

Конечный путь

введите описание изображения здесь

Остается скопировать эти исправления из векторного редактора и добавить их в свой код.

Я заменил код вашего скрипта. Вероятно, вы можете использовать любой скрипт, который выполняет триггерные функции.

 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:

Я расширю комментарий Роберта.

Спецификация SVG гласит:

Для анимации два значения общего свойства могут быть плавно интерполированы только тогда, когда строки данных пути содержат одинаковую структуру (т. Е. Точно такое же количество и типы команд данных пути, которые находятся в том же порядке). Если задана анимация и списки команд данных пути не имеют одинаковой структуры, то значения должны быть интерполированы с использованием дискретного типа анимации.

Однако ваши два пути не имеют одинаковой структуры. Первый путь:

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. Спасибо! Я смог достичь желаемого результата и продвинуться вперед с анимацией. Спасибо за вашу помощь. Это было большим подспорьем в определении того, с какой точкой я имел дело: ссылка После того, как я смог сопоставить команды в более идеальном месте, я закончил тем, что изменил тип анимации на сплайн, чтобы получить более контролируемый эффект простоты. Еще раз спасибо!