这个SVG动画怎么实现的啊?

5,151 阅读4分钟

stroke(描边)和 fill(填充)是svg中非常重要的属性,用于定义和控制形状的外观和可视效果

直接上效果 Img

属性介绍

  • stroke:定义svg的轮廓线 常用css属性有 stroke-dasharray(描边的样式),stroke-dashoffset(起始位置),stroke-color(描边的颜色),stroke-opacity(描边的透明度),stroke-linejoin(描边的拐角样式)等等
  • fill:定义svg内部颜色或图案 ,常用css属性有fill-opacity(定义填充的透明度),fill-rule(定义填充规则),fill-pattern(定义填充的图案)

一般svg标签还包含这几个属性

<svg
    xmlns="http://www.w3.org/2000/svg"  <!-- 命名空间声明指定文档类型 -->
    viewBox="0 0 50 50"  <!-- 定义可视区域的坐标系统,范围是从 (0, 0) 到 (50, 50) -->
    width="400px"  <!-- svg宽度为400px -->
    height="400px"  <!-- svg高度为400px -->
    fill="#EE3E55"  <!-- svg填充颜色为 #EE3E55 -->
    stroke="#000000"  <!-- svg描边颜色为 #000000 -->
>

stroke-dasharray

提供一个数列,其中数与数之前用逗号隔开,交替指定短划线和缺口的长度 比如说

<svg
  width="200"
  height="200"
  viewPort="0 0 200 300"
  version="1.1"
  xmlns="http://www.w3.org/2000/svg">
  <line stroke-dasharray="5, 5" x1="10" y1="10" x2="190" y2="10" />
  <style>
    <![CDATA[
    line{
        stroke: black;
        stroke-width: 2;
    }
    ]]>
  </style>
</svg>

stroke-dasharray="5, 5" x1="10" y1="10" x2="190" y2="10"表示在坐标(10,10)到(190,10)这条水平线上,短划线和缺口都为5个单位 Img

再举个奇数个数的数列,(如果为奇数个, 那个会将这个数列复制一个补上成为偶数数列,比如"10, 5, 20" -> "10, 5, 20, 10, 5, 20")

<line stroke-dasharray="10, 5, 20" x1="10" y1="10" x2="190" y2="10" />

Img

stroke-dashoffset

定义沿SVG路径的短划线的开始位置,数字越大,虚线将沿着路径开始得越远

.path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 0;
  animation: dash 5s linear alternate infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: 1000;
  }
}

我们给svg的path定义三个属性,设置dasharray为1000,并且起始的offset为0,animation的结束状态offset定义为1000,也就是虚线的短划线最末位置 那么就可以实现从无到有,短划线慢慢连接整个path

fill-opacity

fill-opacity如果不设置默认为1,即不透明。可设置为小数,百分数和css属性

<svg viewBox="0 0 400 100" xmlns="http://www.w3.org/2000/svg">
  <!-- 默认 fill opacity: 1 -->
  <circle cx="50" cy="50" r="40" />
  <circle cx="150" cy="50" r="40" fill-opacity="0.7" />
  <circle cx="250" cy="50" r="40" fill-opacity="50%" />
  <circle cx="350" cy="50" r="40" style="fill-opacity: .25;" />
</svg>

效果 Img

实现 Naruto logo

这个icons8网站icons种类很多,一般都能找到想要的 挑选一个icons Img

SVG形式download下来 Img

html结构

结构非常简单,就是一个h标签,svg图片居中和图片animation

<body>
    <h1>Svg animation</h1>
    <div>
        <svg
            fill="#EE3E55"
            stroke="#000000"
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 50 50"
            width="400px"
            height="400px"
        >
            <path
                d="M 27.001953 4.7832031 C 21.502168 4.7913231 16.084635 7.0942615 11.775391 11.712891 C 8.9776265 14.711466 7.3813325 18.362441 6.9257812 22.123047 L 6.8945312 22.111328 L 0.60546875 39.65625 A 2.50025 2.50025 0 0 0 2.9570312 43 L 24.5 43 L 24.5 42.988281 C 29.014184 43.021879 33.503253 41.295882 36.75 37.816406 C 41.787713 32.417359 41.661726 23.713513 36.474609 18.341797 C 34.205785 15.991774 31.257883 14.347174 28.025391 14.019531 C 24.792898 13.691889 21.300039 14.850176 18.636719 17.679688 C 14.965423 21.580089 15.030888 27.929371 18.804688 31.802734 C 20.110475 33.143171 21.837673 34.081121 23.804688 34.400391 C 25.771701 34.71966 28.124829 34.278332 29.849609 32.615234 C 31.25841 31.256679 31.700263 29.427641 31.544922 27.736328 C 31.389581 26.045015 30.586537 24.270043 28.878906 23.21875 A 2.50025 2.50025 0 1 0 26.257812 27.476562 C 26.327182 27.519272 26.526044 27.775172 26.564453 28.193359 C 26.602863 28.611547 26.428106 28.96818 26.378906 29.015625 C 25.894687 29.482527 25.393955 29.592824 24.605469 29.464844 C 23.816982 29.336863 22.88993 28.831017 22.386719 28.314453 A 2.50025 2.50025 0 0 0 22.384766 28.3125 C 20.700564 26.583864 20.694592 22.79102 22.279297 21.107422 C 23.990977 19.288933 25.695227 18.809033 27.521484 18.994141 C 29.347742 19.179248 31.31973 20.199476 32.878906 21.814453 C 36.177789 25.230737 36.226037 31.049298 33.09375 34.40625 C 28.927093 38.871575 21.59531 39.235442 16.800781 35.132812 C 10.557183 29.79014 9.9899143 20.955356 15.431641 15.123047 C 18.908396 11.396676 22.853849 9.7893348 27.007812 9.7832031 C 31.161777 9.7770731 35.595243 11.454532 39.703125 14.78125 A 2.50025 2.50025 0 0 0 42.771484 14.84375 L 48.537109 10.541016 A 2.50025 2.50025 0 1 0 45.546875 6.5332031 L 41.220703 9.7617188 C 36.786163 6.6077415 31.90364 4.7759677 27.001953 4.7832031 z M 8.546875 32.314453 C 9.4995553 34.379835 10.825268 36.313663 12.541016 38 L 6.5097656 38 L 8.546875 32.314453 z"
            />
        </svg>
    </div>
        <button>animation</button> 
	</body>

style基本样式

基本样式也很简单 flex一把梭

body {
	display: flex;
	justify-content: center;
	align-items: center;
	flex-direction: column;
	height: 100vh;
	padding: 200px;
	margin: auto;
	text-wrap: nowrap;
}
div {
	width: 400px;
	height: 400px;
	padding: 100px;
	border-radius: 50%;
	background-color: #ceece5;
	display: flex;
	justify-content: center;
	align-items: center;
	margin: 2rem 0;
}
button {
	border: 1px solid #000;
	color: #000;
	background-color: white;
	padding: 1rem 2rem;
}

stroke fill实践

svg path {
	stroke-dasharray: 500;
	stroke-dashoffset: 0;
    stroke-width: 1;
	fill-opacity: 0;    
}
.animation {
	animation: line 3s linear forwards, fill 1s linear forwards 2s;
}
@keyframes line {
	to {
		stroke-dashoffset: 500;
	}
}
@keyframes fill {
	to {
		fill-opacity: 1;
	}
}
  • stroke-dasharray: 500; 设短划线的长度为500个单位
  • stroke-dashoffset: 0; 初始偏移单位为0
  • stroke-width: 1; 描边宽度为1单位
  • fill-opacity: 0; 透明度为0 不可见
  • line animation 是画线的,to 设置结束状态偏移单位为500个单位,即划线长度的末端 也就是说line animation会从无到慢慢连接整个path
  • fill animation to设置结束状态透明度为1 完全可见

button控制animation触发

DOMContentLoaded 文档内容加载完后执行,然后path直接添加animation样式 btn被点击时先移除animation,再用setTimeout重新添加animation,在下一个事件循环中,path.classList.add('animation') 被添加到宏任务队列中 It works!

document.addEventListener('DOMContentLoaded', () => {
	const path = document.querySelector('svg path')
	const btn = document.querySelector('button')

	path.classList.add('animation')
	btn.addEventListener('click', () => {
		path.classList.remove('animation')
		setTimeout(() => {
			path.classList.add('animation')
		})
	})
})

完整代码

参考