同一对象上不同变换动画的SVG链

时间:2018-12-20 17:43:56

标签: animation svg svg-animate smil

我正在尝试使用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 :(得分:1)

如果您使用的动画具有to属性,但没有from,则使用的起始值是当前属性值。对于每个步骤,都会删除上一步的frozen值,并将其重新输入为隐式from。因此additive="sum"无效。您需要从0开始每个步骤,然后每次都写相对翻译。

但是您的动画还有其他一些缺陷:首先。持续时间0.02s或更短只是瞬间。浏览器不会使用每秒60帧以上的帧速率,这意味着每帧的持续时间为0.0167s。我的建议是,以不连续的步骤从一种状态到另一种状态进行动画处理,并以此完成。您可以在values的列表上按keyTimes的顺序编写动画。

然后必须绝对为每个步骤编写平移和旋转:

  • 翻译以0 0;0 28;0 65;0 93;0 121的顺序进行,持续4 * 0.8s
  • 旋转按顺序0;0;0;90 56 0;90 56 0进行,延迟0.2秒,但持续时间相同

第二个问题与变换的应用顺序有关:旋转,当它们已经向下移动时应用于块时,必须要么使其旋转中心也向下移动,要么必须相乘< em>左侧。

我认为最简单的变体是将块包装在另一个<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>