SVG动画改变元素层级的问题。

平行画
  • 9

题目描述

如何实现下图svg动画
clipboard.png

相关代码

我只能实现出平面效果,想不出解决方案了

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-400 -400 800 800">
    <g id='circle'>
        <!--右边的圆-->
        <circle id="right" cx="50" cy="0" r="50" fill="rgb(102,85,204)">
        <!--右圆动画-->
            <animate 
                id="right_go_left" 
                attributeName="cx" 
                attributeType="XML" 
                begin="0; right_go_right.end" 
                dur="0.5s" 
                from="50" 
                to="-50"
                />
            <animate id="right_go_right" 
                attributeName="cx" 
                attributeType="XML" 
                begin="right_go_left.end" 
                dur="0.5s" 
                from="-50" 
                to="50"
                />
        </circle>
        <!--左边的圆-->
        <circle id='left' cx="-50" cy="0" r="50" fill="rgb(255,0,153)">
        <!--左圆动画-->
            <animate 
                id="left_go_right" 
                attributeName="cx" 
                attributeType="XML" 
                begin="0; left_go_left.end" 
                dur="0.5s" 
                from="-50" 
                to="50"
                />
            <animate 
                id="left_go_left" 
                attributeName="cx" 
                attributeType="XML" 
                begin="left_go_right.end" 
                dur="0.5s" 
                from="50" 
                to="-50"
                />
        </circle>
    </g>
</svg>
回复
阅读 2.7k
2 个回答
✓ 已被采纳

svg 的层叠关系由元素先后定义并加入决定的
如果要调整层叠关系,使用insertBefore并不能起到效果
所以要用占坑法
定义一些多余的 g 标签在需要动态调整层级的位置
然后动态地加入
起到覆盖与被覆盖的作用

动态移动两个元素的 顺序

杨晓帆
  • 2
新手上路,请多包涵

你好,一年过去了,相信你已经得到了满意的答案。那我就给出一种我调试出的解决方案,供看到这里的朋友参考。效果图如下:
测试3.gif
这个动画需要改变蓝色圆和粉色圆的上下层次顺序,但是我们在书写SVG时,从上到下的书写顺序即是图层由底层至顶层的呈现顺序。作为初学者,动态改变图层顺序我暂时还没有找到方法。在其它文档中,我看到关于Z-index的方法来控制Z轴图层顺序,但是好像并不适用于SVG。
但通过观察,我发现并不一定要通过控制两个圆的图层顺序来实现,或许一个“障眼法”就可以。也就是说,我们表面上看到两个圆在交替运动,实际上,是四个圆。
由底层至顶层,依次是“底层蓝圆——底层粉圆——顶层粉圆——顶层蓝圆”。让我们把这个循环动画拆分为两部分:
当我们看到底层粉圆在上向右运动,底层蓝圆在下向左运动时,顶层的蓝圆和粉圆是透明不可见的;
当我们看到顶层蓝圆在上向右运动,底层粉圆在下向左运动时,底层的粉圆和蓝圆是透明不可见的。
由此思路,我们按照图层顺序写下这四个圆,然后动画控制它们的运动轨迹和透明度变化的时机即可。
代码如下:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-400 -400 800 800">
    <g id='circle'>
        <!--底层蓝圆-->
        <circle id="bottom_blue" cx="50" cy="0" r="50" fill="rgb(102,85,204)">
        <!--底层蓝圆向左移动动画-->
            <animate 
                id="bottom_blue_move" 
                attributeName="cx" 
                attributeType="XML" 
                begin="0;bottom_blue_appear.end" 
                dur="0.5s" 
                from="50" 
                to="-50"
                />
        <!--底层蓝圆消失动画-->
            <animate id="bottom_blue_disappear" 
                attributeName="opacity" 
                begin="bottom_blue_move.end" 
                dur="0.5s"
                calcMode="linear" 
                values="1;0;0"
                keyTimes="0;0.0001;1"
                />
        <!--底层蓝圆向右移动返回动画-->
            <animate 
                id="bottom_blue_back" 
                attributeName="cx" 
                attributeType="XML" 
                begin="bottom_blue_move.end" 
                dur="0.5s" 
                from="-50" 
                to="50"
                />
        <!--底层蓝圆出现动画-->
            <animate id="bottom_blue_appear" 
                attributeName="opacity" 
                begin="bottom_blue_back.end" 
                dur="0.0001s"
                calcMode="linear" 
                values="0;1;1"
                keyTimes="0;0.0001;1"
                />
        </circle>
        <!--底层粉圆-->
        <circle id='bottom_pink' cx="-50" cy="0" r="50" fill="rgb(255,0,153)">
        <!--底层粉圆向右移动动画-->
            <animate 
                id="bottom_pink_move" 
                attributeName="cx" 
                attributeType="XML" 
                begin="0;bottom_pink_appear.end" 
                dur="0.5s" 
                from="-50" 
                to="50"
                />
        <!--底层粉圆消失动画-->
            <animate 
                id="bottom_pink_disappear" 
                attributeName="opacity" 
                begin="bottom_pink_move.end" 
                dur="0.5s"
                calcMode="linear" 
                values="1;0;0"
                keyTimes="0;0.0001;1"
                />
        <!--底层粉圆向左移动返回动画-->
            <animate 
                id="bottom_pink_back" 
                attributeName="cx" 
                attributeType="XML" 
                begin="bottom_pink_move.end" 
                dur="0.5s" 
                from="50" 
                to="-50"
                />
        <!--底层粉圆出现动画-->
            <animate 
                id="bottom_pink_appear" 
                attributeName="opacity" 
                begin="bottom_pink_back.end" 
                dur="0.0001s"
                calcMode="linear" 
                values="0;1;1"
                keyTimes="0;0.0001;1"
                />
        </circle>
        <!--顶层粉圆-->
        <circle id="top_pink" cx="50" cy="0" r="50" fill="rgb(255,0,153)" opacity="0">
        <!--顶层粉圆出现动画-->
            <animate 
                id="top_pink_appear" 
                attributeName="opacity"  
                begin="bottom_pink_move.end" 
                dur="0.5s"
                calcMode="linear" 
                values="0;1;1"
                keyTimes="0;0.0001;1"
                />
        <!--顶层粉圆向左移动动画-->
            <animate id="top_pink_move" 
                attributeName="cx"
                attributeType="XML" 
                begin="bottom_pink_move.end" 
                dur="0.5s" 
                from="50" 
                to="-50"
                />
        <!--顶层粉圆消失动画-->
            <animate 
                id="top_pink_disappear" 
                attributeName="opacity"  
                begin="top_pink_move.end" 
                dur="0.5s"
                calcMode="linear" 
                values="1;0;0"
                keyTimes="0;0.0001;1"
                />
        <!--顶层粉圆向右返回动画-->
            <animate id="top_pink_back" 
                attributeName="cx"
                attributeType="XML" 
                begin="top_pink_disappear.end" 
                dur="0.5s" 
                from="-50" 
                to="50"
                />
        </circle>
        <!--顶层蓝圆-->
        <circle id="top_blue" cx="-50" cy="0" r="50" fill="rgb(102,85,204)" opacity="0">
        <!--顶层蓝圆出现动画-->
            <animate 
                id="top_blue_appear" 
                attributeName="opacity"  
                begin="bottom_blue_move.end" 
                dur="0.5s"
                calcMode="linear" 
                values="0;1;1"
                keyTimes="0;0.0001;1"
                />
        <!--顶层蓝圆向右移动动画-->
            <animate id="top_blue_move" 
                attributeName="cx"
                attributeType="XML" 
                begin="bottom_blue_move.end" 
                dur="0.5s" 
                from="-50" 
                to="50"
                />
        <!--顶层蓝圆消失动画-->
            <animate 
                id="top_blue_disappear" 
                attributeName="opacity"  
                begin="top_blue_move.end" 
                dur="0.5s"
                calcMode="linear" 
                values="1;0;0"
                keyTimes="0;0.0001;1"
                />
        <!--顶层蓝圆向左返回动画-->
            <animate id="top_blue_back" 
                attributeName="cx"
                attributeType="XML" 
                begin="top_blue_disappear.end" 
                dur="0.5s" 
                from="50" 
                to="-50"
                />
        </circle>
    </g>
</svg>

如有问题欢迎继续提问,各位如果有更好的解决方案(比如可以动态控制图层上下关系的)请提出来,我也想进一步学习一下。

你知道吗?

宣传栏