目录
入门了svg的基本知识后接下来进阶svg动画。
动画类型
svg的动画类型可以分类css和html标签两种方式来实现。
css类型
说明
svg动画
svg为dom元素可以很好的和css结合
css样式中的stroke-dasharray为svg专用的线段间隔
这里有个需要注意的地方!!!封装svg的"总svg"标签被加上display: none样式后,通过id引用之后的css动画无效化
描边
主要是css样式的stroke-dashoffset偏移和stroke-dasharray虚线间隔属性stroke-linecap较宽的线角上的形状
document.getElementsById('svg').getTotalLength()可以获得对应svg 的绘制长度可以用css相关的长度中
html
useEffect(() => {
setTimeout(() => {
const SVGstrokeLength: any = document.getElementsByClassName('logo')[0]
console.log(SVGstrokeLength.getTotalLength()) // 获取svg的path画图长度
}, 1000)
}, [])
return (
<svg
width="200"
height="200"
viewBox="0 0 200 200"
className='logoBox'
preserveAspectRatio="xMidYMid meet">
<g viewBox='0 0 100 100'>
<circle
cx='50'
cy='50'
r='45'
strokeWidth='5'
stroke='#fff'
fill='transparent'></circle>
<circle
className="SVG_circle"
cx='50'
cy='50'
r='45'
strokeWidth='5'
stroke='green'
fill='transparent'></circle>
</g>
<g viewBox='0 0 100 100'> {/*描边*/}
<line y1='45' x1='10' x2='90' y2='45' className='logo' stroke='red' strokeWidth='10'></line>
</g>
</svg>
)
css
@keyframes circle {
from {
stroke-dasharray: 0 283;/*svgz中的线段间隔*/
}
to {
stroke-dasharray: 283 283;
}
}
.SVG_circle{
animation: circle 5s linear infinite;
}
.logo{
stroke-dasharray: 90;
stroke-dashoffset: 90;
transition: stroke-dashoffset 0.5s ease-out;
}
.logoBox{
&:hover{
.logo{
stroke-dashoffset: 0;
}
}
}
效果
标签类型
说明
tranform变换
translate位移
rotate旋转
skewX和skewY倾斜
scale缩放
matrix复杂变形
SMIL:通过html标签实现svg动画主要是以下几种标签(无需js和css不支持ie)
<set>
设置属性的变化例如<set attributeName='x' attributeType='XML' to='20' begin='2s' />
begin='2'为2秒后开始,attributeName='x'为改变x这个属性
attributeType='XML'为可以对svg属性进行修改为'CSS'时可以对css修改
<animate>
同set一样属性变化但是具有动画效果例如<animate attributeName='cx' attributeType='XML' from='0' to='25' repeatCount='2' dur='2s' fill='remove'></animate>
其中fill='remove'是动画结束回到原点fill='freeze'动画定个在最后一格
dur='2s'为每次动画进行2秒
repeatCount='2'为动画进行两次当等于indefinite为无限循环
<animateColor>
即<animate attributeName='fill'></animate>
<animateTransform>
对比animate多了type属性主要值为svg的transform变换类型
type为rotate时from='0 100 100'表示从0开始以(100, 100)点为圆心旋转
from和to传入多个值时可以用values='0 100 100;360 100 100'或values='red;blue;red'
<animateMotion>
可以让图形沿着path轨迹运动
rotate='auto'代表在路径上运动过程中的转弯策略roeetate='0'在拐弯的时候就不会发生抖动
path属性代表沿着这条路径运动
begin属性
可以通过animateMotion上的id来获取animateMotion动画的结束时间如begin='forword.end + 0.5s'
begin='0; backword.end + 0.5s'表示下一次循环在上一次循环之后继续进行造成无限循环
begin='forword.click'表示可以通过id为forword的svg标签点击之后执行
html
<svg
width="200"
height="200"
viewBox="0 0 200 200"
className='logoBox'
preserveAspectRatio="xMidYMid meet">
<def>
<linearGradient id='linearGradient'>
<stop offset='0' stopColor='red'></stop>
<stop offset='50%' stopColor='green' stopOpacity='0.5'></stop>
<stop offset='100%' stopColor='blue'></stop>
</linearGradient>
<radialGradient r='50%' cx='50%' cy='50%' fx='50%' fy='50%' id='radialGradient'>
<stop offset='0' stopColor='red'></stop>
<stop offset='50%' stopColor='green' stopOpacity='0.5'></stop>
<stop offset='100%' stopColor='blue'></stop>
</radialGradient>
<symbol id='linearGradientBox' viewBox='0 0 100 100'>
<rect x='0' y='0' height='100' width='100' fill='url(#radialGradient)'></rect>
</symbol>
<symbol id='loading' viewBox='0 0 200 200' fill='none'>
<circle cx='100' cy='100' stroke='red' strokeWidth='10' r='90' strokeDasharray='142' strokeLinecap='round'>
<animateTransform attributeName='transform' type='rotate' from='0 100 100' to='360 100 100' dur='3s' repeatCount='indefinite'></animateTransform>
<animate attributeName='stroke' values='red;blue;red' dur='6s' repeatCount='indefinite'></animate>
</circle>
<circle cx='100' cy='100' stroke='blue' strokeWidth='10' r='60' strokeDasharray='94' strokeLinecap='round'>
<animateTransform attributeName='transform' type='rotate' values='360 100 100;0 100 100' dur='3s' repeatCount='indefinite'></animateTransform>
<animate attributeName='stroke' values='blue;red;blue' dur='6s' repeatCount='indefinite'></animate>
</circle>
</symbol>
</def>
<svg viewBox='-50 0 100 100'>
<rect x='0' y='0' height='50' width='50' fill='red'>
<set attributeName='x' attributeType='XML' to='20' begin='1s' />
<set attributeName='x' attributeType='XML' to='20' begin='2s' />
<set attributeName='fill' attributeType='XML' to='blue' begin='3s' />
</rect>
</svg>
<svg viewBox='-50 -50 100 100'>
<circle cx='0' cy='0' r='24' stroke='red' strokeWidth='1' fill='blue'>
<animate attributeName='cx' attributeType='XML' from='0' to='25' repeatCount='2' dur='2s' fill='freeze'></animate>
<animate attributeName='cy' attributeType='XML' from='0' to='25' repeatCount='1' dur='2s' fill='freeze'></animate>
<animateTransform attributeName='transform' attributeType='XML' begin='0' from='1' to='2' dur='3s' type='scale' repeatCount='2'></animateTransform>
</circle>
</svg>
<svg viewBox='0 -50 100 100'>
<rect x='0' y='0' height='10' width='10' fill='red'>
<animateMotion id='forword' begin='0' dur='5s' rotate='0' fill='freeze' path='M10 10 L10 30 L30 30 L30 10 Z'></animateMotion>
<animateMotion id='back' begin='forword.end + 0.5s' dur='5s' rotate='0' fill='freeze' path='M30 10 L30 30 L10 30 L10 10 Z'></animateMotion>
</rect>
{/* 下面的path标签可以不用 */}
<path d='M10 10 L10 30 L30 30 L30 10 Z' fill='none' stroke='green'></path>
</svg>
</svg>
<span style={{color: 'green', display: 'block'}}>
<Icon style={{width: 100, height: 100}} svgId='loading' />
<Icon style={{width: 100, height: 100}} svgId='linearGradientBox' />
</span>
效果
总结
无论是css还是标签都可以实现svg动画各有独特的使用场景。标签动画更适用于实现复杂的动画,对于相对简单的动画则可以使用css动画来实现。