马黑黑 发表于 2023-11-21 07:40

svg动画之 animateTransform(一)

<style>
.papa > p { margin: 10px 0; }
.hCode { display: block; padding: 10px 10px 10px 50px; font: normal 15px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; background: #F7EFE6; overflow-x: auto; tab-size: 4; position: relative; }
.hCode::before { position: absolute; content: attr(data-line); left: 0; top: 0; padding: 10px; font: inherit; color: #999; text-align: right; border-right: 1px solid tan; }
.rred { color: red; }
.zs { color: green; }
</style>

<div class="papa">
        <h2>svg动画之 animateTransform(一)</h2>
        <p>animateTransform,从动画名称我们就可以看出,这是一个基于基础变形 transform 的动画。transform 也称转换、形变等,其功能是令对象旋转(rotate)、移位(translate)、缩放(scale)和倾斜(skewX/Y)。虽然 animate 动画元素可以通过改变运动对象的属性达成动画效果,却不能对 transform 转换做任何工作,因为这个工位专由 animateTransform 动画元素负责。</p>
        <p>之前介绍 animate 动画时我们讲到的绝大多数动画属性同样适用于 animateTransform,不过 animateTransform 需要一个额外的属性 type,用以指明 transform 的变形种类是 rotate、translate、scale 和 skewX/Y 中的哪一个,例如:</p>

<pre class="hCode">
        type="translate"
</pre>

        <p>我们先来看看由 animateTransform 驱动的动画效果,请将鼠标指针移至下方图形:</p>

        <svg style="border: 1px solid tan">
                <g id="g1" transform="rotate(15,60 60)">
                        <circle cx="60" cy="60" r="8" transform="translate(60,0) scale(6,1) translate(-60,0)" fill="olive" />
                        <circle cx="60" cy="60" r="8" transform="translate(0,60) scale(1,6) translate(0,-60)" fill="olive" />
                        <circle cx="60" cy="60" r="10" fill="tan" />
                </g>
                <animateTransform
                        xlink:href="#g1"
                        attributeName="transform"
                        type="rotate"
                        from="15,60 60"
                        to="375, 60 60"
                        dur="3s"
                        begin="mouseover"
                        restart="whenNotActive"
                />
        </svg>
       
        <p>代码:</p>

<pre class="hCode">
&lt;svg style="border: 1px solid tan"&gt;
        &lt;g id="g1" transform="rotate(15,60 60)"&gt;
                &lt;circle cx="60" cy="60" r="8" transform="translate(60,0) scale(6,1) translate(-60,0)" fill="olive" /&gt;
                &lt;circle cx="60" cy="60" r="8" transform="translate(0,60) scale(1,6) translate(0,-60)" fill="olive" /&gt;
                &lt;circle cx="60" cy="60" r="10" fill="tan" /&gt;
        &lt;/g&gt;
        &lt;animateTransform
                xlink:href="#g1"
                attributeName="transform"
                <span class="rred">type="rotate"</span>
                from="15,60 60"
                to="375, 60 60"
                dur="3s"
                begin="<span class="rred">mouseover</span>"
                restart="whenNotActive"
        /&gt;
&lt;/svg&gt;
</pre>

        <p>代码解析:首先,我们绘制了三个圆心坐标一致的小圆,前两个小圆在原地分别沿水平和竖直方向放大六倍,并将这三个小圆放到 g 标签里面构成一个小组,g 标签拥有id标识,在原地旋转15度。接着,我们请出 animateTransform 动画元素,它与 g 标签并列,所以通过 xlink:href 属性指明作用对象为 id="g1" 的 g 标签;动画诸多属性中,与之前介绍的 animate 属性绝大多数完全一样,就多一个 type 属性,如前已述,它用来描述 transform 的动画类型。</p>
        <p>当然,这里还有需要注意的地方:一是 g 标签带组问题。g 标签之内的元素作为一个整体由 g 带领,我们的 animateTransform 动画针对的是 g 元素,换言之,动画仅驱动 g 运动,g 标签内的元素因 g 的运动而运动;其二,就是转动(rotate)的衔接问题。上例,g 标签自身转动了15度,如果希望 g 小组转一圈,则 to 的属性值应为 15+360=375 度;其三,例中 begin 属性的 mouseover 值,和 click 一样,属于 SMIL 设计中对 JS 的借鉴,容易理解和记忆。</p>
        <p>下面再看一个移位转换示例,type="translate",单击小圆运行动画:</p>

        <svg style="width: 300px; height: 150px; border: 1px solid gray;">
                <circle cx="30" cy="30" r="30" fill="tan">
                        <animateTransform
                                attributeName="transform"
                                type="translate"
                                values="0,0; 240,90; 0,0"
                                dur="3s"
                                begin="click"
                                restart="whenNotActive"
                                fill="freeze"
                        />
                </circle>
        </svg>

        <p>代码和解释:</p>

<pre class="hCode">
&lt;svg style="width: 300px; height: 150px; border: 1px solid gray;"&gt;
        &lt;circle cx="30" cy="30" r="30" fill="tan"&gt;
                &lt;animateTransform
                        attributeName="transform" <span class="zs">&lt;-- 指定transform为运动属性 --&gt;</span>
                        type="translate" <span class="zs">&lt;-- 指明transform类型为translate --&gt;</span>
                        values="0,0; 240,90; 0,0" <span class="zs">&lt;-- 运动轨迹 --&gt;</span>
                        dur="3s" <span class="zs">&lt;-- 周期运动时长 --&gt;</span>
                        begin="click" <span class="zs">&lt;-- 设定单击为动画触发事件 --&gt;</span>
                        restart="whenNotActive" <span class="zs">&lt;-- 定义重启动画方式 :非活动时可以重启 --&gt;</span>
                        fill="freeze" <span class="zs">&lt;-- 定义动画结束时的状态 :保持最后的姿势 --&gt;</span>
                /&gt;
        &lt;/circle&gt;
&lt;/svg&gt;
</pre>

        <p>再重点解释一下 values 属性的设计:translate是将运动对象进行位移,它支持{x,y}同时移动,写成 translate(x,y)。例中的 values 属性值共三组:第一组 {0,0},小圆元素位移从起点开始,出发点坐标实际上就是小圆所占矩形区域的左上角XY坐标而不是圆心坐标 {cx,cy};第二组 {240,90},在svg的右下角,值参考的也是小圆所占矩形区域的左上角XY坐标,不是圆心。为什么是240和90呢?拿svg的宽高减去圆的直径就可以明白了;第三组 {0,0},位移到原位。所以,这个 values 属性值的设计,就是让圆从左上角出发,到右下角后再位移到左上角的路线。</p>
        <p>阅读至此,应该感受到,animateTransform 动画元素(标签)其实并不复杂,但要掌握它需要有个前提:要弄清svg中基础变形和svg动画相关的基本知识。知识需要前后关联,完好的认知体系就能相对完整地建立起来。</p>

</div>

<script>

let btns = document.querySelectorAll('.btnok'),
        stages = document.querySelectorAll('.stage'),
        hCodes = document.querySelectorAll('.hCode'),
        hLineNums = document.querySelectorAll('.hLineNum');

hCodes.forEach((item,key) => {
        let lines = hCodes.innerText.trim().split('\n').length;
        let str = '';
        for(let i = 0; i < lines; i ++) {
                str += i + 1 + '\n';
        }
        item.dataset.line = str;
});

</script>

红影 发表于 2023-11-21 09:36

位移的这个比较简单,直接作用在小圆上,应该先讲这个再讲那个旋转的,旋转的那个更难点{:4_173:}

红影 发表于 2023-11-21 09:42

animateTransform可以直接作用于元素,也可以作用于 g 标签带的组,且是作用于 g 标签,“g 标签内的元素因 g 的运动而运动”。
上述例子,位移的点位选取左上角,旋转选取的旋转中心是图形中心。

红影 发表于 2023-11-21 09:46

前几堂课讲的 animate 是通过改变对象属性达成动画效果,而animateTransform则可以直接对对象进行旋转、位移、缩放、倾斜的操作,达成动画效果。{:4_204:}
哦,我知道为什么先介绍旋转了,原来是按旋转、位移、缩放、倾斜的顺序介绍的。那么下面一节课应该就是介绍缩放和倾斜了吧,好期待啊{:4_173:}

马黑黑 发表于 2023-11-21 12:20

红影 发表于 2023-11-21 09:46
前几堂课讲的 animate 是通过改变对象属性达成动画效果,而animateTransform则可以直接对对象进行旋转、位 ...

对的,并且,可能不太难

马黑黑 发表于 2023-11-21 12:26

红影 发表于 2023-11-21 09:36
位移的这个比较简单,直接作用在小圆上,应该先讲这个再讲那个旋转的,旋转的那个更难点

其实是一样简单的。你把 g 标签换成一个矩形什么的不就成了?

g 是一个集合,把 g 和它所带的子元素看成一个单位,一切也可以简单。

红影 发表于 2023-11-21 15:55

马黑黑 发表于 2023-11-21 12:20
对的,并且,可能不太难

是的,这个倒是不那么难呢。

红影 发表于 2023-11-21 15:56

马黑黑 发表于 2023-11-21 12:26
其实是一样简单的。你把 g 标签换成一个矩形什么的不就成了?

g 是一个集合,把 g 和它所带的子元素看 ...

嗯嗯,把它看成独立的,其实就跟小圆是一回事了。

马黑黑 发表于 2023-11-21 18:03

红影 发表于 2023-11-21 15:56
嗯嗯,把它看成独立的,其实就跟小圆是一回事了。

g 的作用就是分组,组里所有的东东可以有自己的特性,但都是一个组的,相当于一家人,搬家时是一起搬的

马黑黑 发表于 2023-11-21 18:04

红影 发表于 2023-11-21 15:55
是的,这个倒是不那么难呢。

特别是,越过一些门槛后

红影 发表于 2023-11-21 19:54

马黑黑 发表于 2023-11-21 18:03
g 的作用就是分组,组里所有的东东可以有自己的特性,但都是一个组的,相当于一家人,搬家时是一起搬的

步调一致{:4_173:}

红影 发表于 2023-11-21 19:55

马黑黑 发表于 2023-11-21 18:04
特别是,越过一些门槛后

这些效果都接触过,只是达到的手段不同而已。

马黑黑 发表于 2023-11-22 07:42

红影 发表于 2023-11-21 19:55
这些效果都接触过,只是达到的手段不同而已。

既然已经接触了svg,那么,就尽可能系统地接触它。svg有坐标系统以及坐标系统的变换,这回带来更多的可能。

红影 发表于 2023-11-22 10:28

马黑黑 发表于 2023-11-22 07:42
既然已经接触了svg,那么,就尽可能系统地接触它。svg有坐标系统以及坐标系统的变换,这回带来更多的可能 ...

是的,坐标系统的确认还是挺有关系的。

马黑黑 发表于 2023-11-22 12:15

红影 发表于 2023-11-22 10:28
是的,坐标系统的确认还是挺有关系的。

svg这么设计,肯定有其理由

红影 发表于 2023-11-22 13:53

马黑黑 发表于 2023-11-22 12:15
svg这么设计,肯定有其理由

虽然不知道那理由是什么,但跟着做肯定不会有问题{:4_173:}

马黑黑 发表于 2023-11-22 18:07

红影 发表于 2023-11-22 13:53
虽然不知道那理由是什么,但跟着做肯定不会有问题

弄懂理由那要读研才行,现在俺木有时间带烟酒生

红影 发表于 2023-11-22 19:59

马黑黑 发表于 2023-11-22 18:07
弄懂理由那要读研才行,现在俺木有时间带烟酒生

烟酒生都没本事弄懂啊,那我更不敢想了{:4_173:}

马黑黑 发表于 2023-11-22 20:51

红影 发表于 2023-11-22 19:59
烟酒生都没本事弄懂啊,那我更不敢想了

你博士要厉害一点

红影 发表于 2023-11-22 21:28

马黑黑 发表于 2023-11-22 20:51
你博士要厉害一点

算了吧,我这种从来没搏过的人,博什么士啊{:4_173:}
页: [1] 2 3 4 5
查看完整版本: svg动画之 animateTransform(一)