svg动画

2021-09-02  本文已影响0人  易路先登

1、translate

正常矩形
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red"  />
        </svg>
右移10px
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="translate(10,0)" />
        </svg>
左右各移10px
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="translate(10,10)" />
        </svg>

2、rotate

旋转
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="translate(10,10) rotate(30)"  />
        </svg>

3、skewX(30)倾斜

沿X轴倾斜30度
<svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="translate(10,10) skewX(30)"  />
</svg>

4、skewY

沿Y轴倾斜30度
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="translate(10,10) skewY(30)"  />
        </svg>

5、scale放大缩小

正常
缩小为原来一半
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="translate(10,10) scale(.5)"  />
        </svg>

6、matrix复杂变形

正常形状
复杂变形后
        <!-- 
            [2,-1,50] => 2*_x+(-1)*_y+50 = x
            [1,2,0] =>1*_x+2*_y+0=y
            顶点坐标
            [0,0] => [50,0]
            [100,0] => [250,100]
            [100,50] => [200,200]
            [0,50] => [0,100]
         -->
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect x="0" y="0" width="100" height="50" fill="red" transform="matrix(2 1 -1 2 50 0)"  />
        </svg>

7、环形进度条

stroke-dasharray的用法

散状绘制
<template>
    <div>
    <div class="container">
        <!-- 
            [2,-1,50] => 2*_x+(-1)*_y+50 = x
            [1,2,0] =>1*_x+2*_y+0=y
            顶点坐标
            [0,0] => [50,0]
            [100,0] => [250,100]
            [100,50] => [200,200]
            [0,50] => [0,100]
         -->
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect 
            class="rect"
            x="0" 
            y="0" 
            width="100" 
            height="50" 
            fill="none"
            stroke="blue"
            stroke-width="5" />
        </svg>
    </div>
    <div class="container">
        <svg 
       
        width="400" 
        height="400">
            <circle cx="200" cy="200" r="180" stroke-width="20" stroke="#d1d3d7" fill="none"></circle>
            <circle  
            class="circle" 
            cx="200" 
            cy="200" 
            r="180" 
            stroke-width="20" 
            stroke="#00a5e0" 
            fill="none"></circle>
        </svg>
    </div>
    </div>
</template>
<script setup>

</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
}
.rect{
    stroke-dasharray:10 20 30;
}
.circle{
    stroke-dasharray:10 1131;
}
</style> 

环形动态进度条

进度条.gif
<template>
    <div>
    <div class="container">
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect 
            class="rect"
            x="0" 
            y="0" 
            width="100" 
            height="50" 
            fill="none"
            stroke="blue"
            stroke-width="5" />
        </svg>
    </div>
    <div class="container">
        <svg 
       
        width="400" 
        height="400">
            <circle cx="200" cy="200" r="180" stroke-width="20" stroke="#d1d3d7" fill="none"></circle>
            <circle  
            class="circle" 
            cx="200" 
            cy="200" 
            r="180" 
            stroke-width="20" 
            stroke="#00a5e0" 
            fill="none"></circle>
        </svg>
    </div>
    </div>
</template>
<script setup>

</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
}
.rect{
    stroke-dasharray:10 20 30;
}
.circle{
    animation:circle 5s linear infinite;
}
@keyframes circle{
    from {
        stroke-dasharray:0 1131;
    }
    to {
        stroke-dasharray: 1131 0;
    }
}
</style> 

如果想让起点旋转到正上方,可任意取三点,根据计算公式解出一元三次方程,

            [2,-1,50] => 2*_x+(-1)*_y+50 = x
            [1,2,0] =>1*_x+2*_y+0=y

得出

 transform="matrix(0 -1 1 0 0 400)"

8、矩形动态进度条

rect动态进度条.gif
<template>
    <div>
    <div class="container">
        <svg width="500" height="200" viewBox="0 0 500 200">
            <rect 
            class="rect"
            x="0" 
            y="0" 
            width="100" 
            height="50" 
            fill="none"
            stroke="blue"
            stroke-width="5" />
        </svg>
    </div>
    <div class="container">
        <svg 
       
        width="400" 
        height="400"
        viewBox="0 0 400 400"
        >
            <circle cx="200" cy="200" r="180" stroke-width="20" stroke="#d1d3d7" fill="none"></circle>
            <circle  
            class="circle" 
            cx="200" 
            cy="200" 
            r="180" 
            stroke-width="20" 
            stroke="#00a5e0" 
            fill="none"
            transform="matrix(0 -1 1 0 0 400)"
            ></circle>
        </svg>
    </div>
    <div class="container">
        <svg 
       
        width="200" 
        height="200"
        viewBox="0 0 200 200"
        >
            <rect x="0" y="0" width="200" height="200" stroke-width="8" stroke="grey" fill="none"></rect>
             <rect x="0" y="0" width="200" height="200" stroke-width="8" stroke="blue" fill="none" class="rect-process" transform="matrix(0,1,-1,0,200,0)"></rect>
        </svg>
    </div>
    </div>
</template>
<script setup>

</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
}
.rect{
    stroke-dasharray:10 20 30;
}
.circle{
    animation:circle 5s linear infinite;
}
@keyframes circle{
    from {
        stroke-dasharray:0 1131;
    }
    to {
        stroke-dasharray: 1131 0;
    }
}
.rect-process{
    animation:rect-process 5s linear infinite;
}
@keyframes rect-process{
    from {
        stroke-dasharray:0 800;
    }
    to {
        stroke-dasharray:800 0;
    }
}
</style> 

9、描边动画

(1)、矩形描边


rect描边.gif
    <div class="container">
        <svg class="line-container" width="400" height="400" viewBox="0 0 400 400">
            <line class="line" x1="0" y1="50" x2="400" y2="50" fill="none" stroke-width="20" stroke="red"/>
        </svg>
    </div>
.container{
    border:1px solid #000;
    width:400px;
}
.line {
    stroke-dasharray:400;
    stroke-dashoffset:400;
    transition:stroke-dashoffset .5s ease-out;
}
.line-container:hover .line{
    stroke-dashoffset:0;
}

(2)、心形描边

心描边.gif
获取path长度
const path = documet.getElementById('logo')
const pathLen = path.getTotalLength()
心描边定长.gif
    <div class="container">
        <svg t="1630632068637"  viewBox="0 0 1024 1024"  p-id="1844" width="64" height="64">
            <path class="logo" d="M629.28 200.192a213.056 213.056 0 0 0-111.616 37.28l-5.696 4.032-5.696-4.032a212.704 212.704 0 0 0-120.32-37.472c-120.8 0-217.952 101.568-217.952 225.376 0 59.872 16.768 97.856 56.32 157.216 30.144 45.248 79.104 95.392 140.416 148.48l16.8 14.368 16.32 13.6 15.552 12.64 21.312 16.864 12.48 9.6 10.784 8.064a90.656 90.656 0 0 0 108.256-0.224l15.36-11.52 12.032-9.344 13.216-10.464 14.144-11.456 14.912-12.32 15.424-13.056 7.872-6.72c61.312-53.12 110.272-103.264 140.416-148.48 39.648-59.456 56.384-97.344 56.384-157.248-0.096-123.84-97.28-225.376-218.048-225.376l-8.64 0.192zM637.952 256c89.28 0 161.984 75.968 162.048 169.376 0 45.856-17.664 80.448-35.584 108.8l-7.68 11.744-3.712 5.632c-14.88 22.304-35.232 45.92-57.632 68.992l-12.384 12.48-12.672 12.352-6.4 6.08-12.832 11.904-19.168 17.152-12.48 10.88-18.08 15.36-27.2 22.24-21.824 17.216-19.552 14.88c-11.264 8.384-26.24 9.152-38.176 2.272l-4.128-2.752-18.912-14.4-21.824-17.216-21.44-17.44-11.68-9.76-18.368-15.744-19.008-16.864-12.864-11.744a1183.712 1183.712 0 0 1-6.4-6.016l-12.768-12.192-12.544-12.416c-22.72-22.944-43.744-46.624-59.584-69.152l-4.16-6.112a1241.6 1241.6 0 0 1-7.552-11.392l-7.68-12.16C239.264 500.864 224 467.968 224 425.376 224 331.936 296.64 256 385.984 256c49.6 0 95.648 23.776 125.984 62.976C542.304 279.776 588.384 256 637.952 256z" p-id="1845"></path>
        </svg>
    </div>
.logo{
    fill:none;
    stroke:#333;
    stroke-width:10;
    animation:logos 5s linear forwards;
}
@keyframes logos{
    0% {
        stroke:#333;
        fill:white;
        stroke-dasharray:3812;
        stroke-dashoffset:3812;
    }
    50%{
        stroke:#333;
        fill:white;
        stroke-dasharray:3812;
        stroke-dashoffset:0;
    }
    75%{
        stroke:#aaa;
        fill:red;
    }
    100%{
        stroke:#aaa;
        fill:blue;
    }
}

10、SMIL动画

全称:Synchronized Multimedia Integration Language。通过HTML标签实现动画效果,可以用于:

<set>
<animate>
<animateColor>
<animateTransform>
<animateMotion>

(1)、set用法

set用法.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
            <rect x="0" y="0" fill="red" width="100" height="50">
                <set attributeName="x" attributeType="XML" to="10" begin="1s"></set>
                <set attributeName="x" attributeType="XML" to="20" begin="2s"></set>
                <set attributeName="fill" attributeType="XML" to="blue" begin="3s"></set>
            </rect>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

(2)、animate的用法

SMILanimate.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
            <circle cx="0" cy="0" r="30" fill="blue" stroke="black" stroke-width="2">
                <animate attributeName="cx" attributeType="XML" from="0" to="100" dur="2s" repeatCount="indefinite"></animate>
            </circle>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

attributeType的值有XMLcss,后者的话标识所操作属性从css中获取
fill的值有freeze表示动画停留在截止时状态。remove动画结束时回归原位。

动画可叠加

SMILanimate叠加.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
            <circle cx="0" cy="0" r="30" fill="blue" stroke="black" stroke-width="2">
                <animate attributeName="cx" attributeType="XML" from="0" to="100" dur="2s" repeatCount="1" fill="freeze"></animate>
                <animate attributeName="cy" attributeType="XML" from="0" to="50" dur="2s" repeatCount="1" fill="freeze"></animate>
            </circle>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style>

匪夷所思的补间动画

SMILanimate酷炫.gif
<template>
    <div>
    <div class="container">
        <svg width="400" height="400">
           <polygon fill="#fcc" stroke="black">
               <animate attributeName="points" attributeType="XML" from="30 30 70 30 90 70 10 70" to="50 30 70 50 50 90 30 50" dur="2s" repeatCount="1" fill="freeze"></animate>
           </polygon>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

(3)、animationColor
animationColor已经很少使用(废弃状态),可以使用animate替换

<animate attributeName="fill" from="red" to="blue" dur="5s" repeatCount="indefinite"></animate>

(4)、animateTransform

SMILanimateMotion.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
            <circle cx="0" cy="0" r="30" fill="blue" stroke="black" stroke-width="2">
                <animateTransform attributeName="transform" attributeType="XML" begin="0" dur="2s" type="scale" from="1" to="2" repeatCount="1" fill="freeze"></animateTransform>
            </circle>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

(5)、animateMotion

SMILanimateMotion1.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
           <rect x="0" y="0" fill="red" width="10" height="10">
               <animateMotion
                path="M10 10 L110 10 L110 110 L10 110 Z"
                dur="5s"
                rotate="auto"
                fill="freeze"
                repeatCount="1"
                />
           </rect>
           <path d="M10 10 L110 10 L110 110 L10 110 Z" fill="none" stroke="green"></path>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

rotate值改为0,在转弯处就不会抖动

归程动画

SMILanimateMotion2.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
           <rect x="00" y="0" fill="red" width="10" height="10">
               <animateMotion
                id="forward"
                path="M10 10 L110 10 L110 110 L10 110"
                dur="5s"
                rotate="0"
                fill="freeze"
                begin="0"
                />
                <animateMotion
                id="backward"
                path="M10 110 L110 110 L110 10 L10 10"
                dur="5s"
                rotate="0"
                fill="freeze"
                begin="forward.end"
                />
           </rect>
           <path d="M10 10 L110 10 L110 110 L10 110" fill="none" stroke="green"></path>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

复合归程动画

SMILanimateMotion3.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200">
           <rect x="00" y="0" fill="red" width="10" height="10">
               <animateMotion
                id="forward"
                path="M10 10 L110 10 L110 110 L10 110"
                dur="5s"
                rotate="0"
                fill="freeze"
                begin="0;backward.end+0.5s"
                />
                <animateMotion
                id="backward"
                path="M10 110 L110 110 L110 10 L10 10"
                dur="5s"
                rotate="0"
                fill="freeze"
                begin="forward.end + 0.5s"
                />
                <animate
                id="red-to-blue"
                attributeName="fill"
                attributeType="XML"
                from="red"
                to="blue"
                dur="5s"
                begin="0;backward.end+0.5s"
                fill="freeze"
                 />
                <animate
                id="blue-to-red"
                attributeName="fill"
                attributeType="XML"
                from="blue"
                to="red"
                dur="5s"
                begin="red-to-blue.end+0.5s"
                fill="freeze"
                 />
           </rect>
           <path d="M10 10 L110 10 L110 110 L10 110" fill="none" stroke="green"></path>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 

复杂动画

SMILanimateMotion4.gif
<template>
    <div>
    <div class="container">
        <svg width="200" height="200" viewBox="0 0 200 200">
           <g id="rect1">
               <rect x="0" y="0" rx="0" ry="0" width="100" height="100" fill="red">
                   <animate
                    attributeType="XML"
                    attributeName="fill"
                    from="red"
                    to="green"
                    begin="rect1.click"
                    dur="2s"
                    fill="freeze"
                   ></animate>
               </rect>
           </g>
           <animateTransform
                attributeType="XML"
                attributeName="transform"
                type="translate"
                from="0,0"
                to="50,50"
                begin="rect1.click"
                dur="2s"
                fill="freeze"
            />
           <rect x="0" y="100" width="100" height="100" fill="blue">
               <animate
                attributeType="XML"
                attributeName="fill"
                from="blue"
                to="green"
                fill="freeze"
               ></animate>
           </rect>
        </svg>
    </div>
    </div>
</template>
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
    
})
</script>
<style type="text/css" scoped>
.container{
    border:1px solid #000;
    width:200px;
}
</style> 
上一篇下一篇

猜你喜欢

热点阅读