SVG цепочка различных анимаций трансформации на одном и том же объекте - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь создать анимацию падающего блока тетриса, используя SVG, который включает в себя перевод и вращение фрагмента.Я использовал отдельные анимации для каждого хода, чтобы они выглядели как можно ближе к игре.Анимация падения работает, но как только я пытаюсь повернуть фигуру, она не сохраняет вращение и возвращается к исходному вращению (0) при следующем движении.Есть ли какой-нибудь способ заставить часть вращаться, или, может быть, даже лучше, как я могу реализовать анимацию?

Заранее спасибо за вашу помощь.

<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="280" height="504" xmlns:xlink="http://www.w3.org/1999/xlink">

<defs>
<g id ="b_lightblue">
        <rect x="20" y="20" width="20" height="20" fill="#00F0F0"/>
        <polyline points="20 20, 16 16, 44 16, 40 20, 20 20" fill="#B3FBFB"/>
        <polyline points="40 20, 44 16, 44 44, 40 40, 40 20" fill="#00D8D8"/>
        <polyline points="40 40, 44 44, 16 44, 20 40, 40 40" fill="#007878"/>
        <polyline points="20 40, 16 44, 16 16, 20 20, 20 40" fill="#00D8D8" />
</g>   
<g id ="tetro_I">
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(-16 -16)"/>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(12 -16)"/>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(40 -16)"/>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(68 -16)"/>    
</g>
</defs>

<rect x="0" y="0" width="280" height="504" fill="#CDCEAE"/> <!--Background-->
<use id="tetro_1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#tetro_I" transform="translate(84 28) rotate(0)" opacity="1"/> <!--Tetris Piece-->

<animateTransform xlink:href="#tetro_1" id="t1_move_1" attributeName="transform" type="translate" begin="0.8s" dur="0.02" from="84 28" to="84 65" fill="freeze"/> 
<animateTransform xlink:href="#tetro_1" id="t1_move_2" attributeName="transform" type="translate" additive="sum" begin="t1_move_1.end+0.8s" dur="0.02" to="84 65" fill="freeze"/>
<animateTransform xlink:href="#tetro_1" id="t1_move_3" attributeName="transform" type="translate" additive="sum" begin="t1_move_2.end+0.8s" dur="0.02" to="84 93" fill="freeze"/>
<animateTransform xlink:href="#tetro_1" id="t1_rotate_1" attributeName="transform" type="rotate" additive="sum" begin="t1_move_3.end+0.2s" dur="0.001" from="0" to="90 56 0" fill="freeze"/>
<animateTransform xlink:href="#tetro_1" id="t1_move_4" attributeName="transform" type="translate" additive="sum" begin="t1_move_3.end+0.8s" dur="0.02" to="84 121" fill="freeze"/>

</svg>

1 Ответ

0 голосов
/ 20 декабря 2018

Если вы используете анимацию с атрибутом to, но без from, начальным значением будет текущее значение атрибута.Для каждого шага значение frozen из предыдущего шага удаляется и повторно вводится как неявное from.Поэтому additive="sum" не может иметь никакого эффекта.Вам нужно будет начинать каждый шаг с 0, а затем каждый раз писать относительно переводов.

Но у вашей анимации есть и другие недостатки: Во-первых.длительность 0,02 с или меньше - только мгновенная.Браузеры не используют частоту кадров выше 60 кадров в секунду, что означает, что продолжительность каждого кадра составляет 0,0167 с.Мой совет состоял бы в том, чтобы анимировать из одного состояния в другое отдельными шагами и покончить с этим.Вы можете записать анимацию как последовательность values поверх списка keyTimes.

И перевод, и вращение должны быть записаны абсолютно для каждого шага:

  • переводыидти в последовательности 0 0;0 28;0 65;0 93;0 121 в течение 4 * 0,8 с
  • вращения идут в последовательности 0;0;0;90 56 0;90 56 0, с задержкой на 0,2 секунды, но с той же продолжительностью

Вторая проблема связана с порядком применения преобразований: вращение, когда оно применяется к блокам в то время, когда они уже сместились, должно либо смещать центр вращения, либо умножаться на влево переводов.

Я думаю, что самый простой вариант - заключить блок в другой элемент <g>, применить перевод к этой группе и поворот к элементу <use> внутри.Таким образом, порядок сохраняется.

<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="280" height="504" xmlns:xlink="http://www.w3.org/1999/xlink">

<defs>
<g id ="b_lightblue">
        <rect x="20" y="20" width="20" height="20" fill="#00F0F0"/>
        <polyline points="20 20, 16 16, 44 16, 40 20, 20 20" fill="#B3FBFB"/>
        <polyline points="40 20, 44 16, 44 44, 40 40, 40 20" fill="#00D8D8"/>
        <polyline points="40 40, 44 44, 16 44, 20 40, 40 40" fill="#007878"/>
        <polyline points="20 40, 16 44, 16 16, 20 20, 20 40" fill="#00D8D8" />
</g>   
<g id ="tetro_I">
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(-16 -16)"/>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(12 -16)"/>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(40 -16)"/>
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#b_lightblue" transform="translate(68 -16)"/>    
</g>
</defs>

<rect x="0" y="0" width="280" height="504" fill="#CDCEAE"/> <!--Background-->
<g id="tetro_move_1">
  <use id="tetro_rotate_1" xlink:href="#tetro_I" transform="translate(84 0)"/>
</g> <!--Tetris Piece-->

<animateTransform xlink:href="#tetro_move_1" attributeName="transform" type="translate"
                  begin="0s" dur="3.2s" fill="freeze" additive="sum" calcMode="discrete"
                  values="0 0;0 28;0 65;0 93;0 121"
                  keyTimes="0;0.25;0.5;0.75;1"/> 
<animateTransform xlink:href="#tetro_rotate_1" attributeName="transform" type="rotate"
                  begin="0.2s" dur="3.2s" fill="freeze" additive="sum" calcMode="discrete"
                  values="0;0;0;90 56 0;90 56 0;"
                  keyTimes="0;0.25;0.5;0.75;1"/> 

</svg>
...