这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
介绍
大家可能经常在一些数据可视化的网站见到一些绕着盒子循环科技感十足的动画,或者是玩游戏背包的一些特殊道具也有这些效果,本期会用svg写一个这样的飞盒动画头像框。
先康康效果吧:
正文
1.基本结构
<div class="main">
<div class="box">
<img src="./assets/face.jpg">
<svg viewBox="0,0,300,300">
<!-- ... -->
</svg>
</div>
</div>
我们会在div.main铺满全屏绘制一个扩散背景,而且用弹性布局是其div.box居中,没别的目的都是就为了大背景好看点,嘻嘻。。
.main {
width: 100%;
min-height: 100vh;
padding: 0;
text-align: center;
overflow: hidden;
font-size: 14px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
background-image: radial-gradient(circle at center center, transparent,rgb(0,0,0)),linear-gradient(114deg, rgba(59, 59, 59,0.05) 0%, rgba(59, 59, 59,0.05) 50%,rgba(63, 63, 63,0.05) 50%, rgba(63, 63, 63,0.05) 100%),linear-gradient(186deg, rgba(173, 173, 173,0.05) 0%, rgba(173, 173, 173,0.05) 50%,rgba(237, 237, 237,0.05) 50%, rgba(237, 237, 237,0.05) 100%),linear-gradient(98deg, rgba(191, 191, 191,0.05) 0%, rgba(191, 191, 191,0.05) 50%,rgba(119, 119, 119,0.05) 50%, rgba(119, 119, 119,0.05) 100%),linear-gradient(58deg, rgba(95, 95, 95,0.05) 0%, rgba(95, 95, 95,0.05) 50%,rgba(189, 189, 189,0.05) 50%, rgba(189, 189, 189,0.05) 100%),linear-gradient(259deg, rgba(31, 31, 31,0.05) 0%, rgba(31, 31, 31,0.05) 50%,rgba(110, 110, 110,0.05) 50%, rgba(110, 110, 110,0.05) 100%),linear-gradient(41deg, rgba(142, 142, 142,0.05) 0%, rgba(142, 142, 142,0.05) 50%,rgba(84, 84, 84,0.05) 50%, rgba(84, 84, 84,0.05) 100%),linear-gradient(134deg, rgba(96, 96, 96,0.05) 0%, rgba(96, 96, 96,0.05) 50%,rgba(198, 198, 198,0.05) 50%, rgba(198, 198, 198,0.05) 100%),linear-gradient(46deg, rgba(12, 12, 12,0.05) 0%, rgba(12, 12, 12,0.05) 50%,rgba(71, 71, 71,0.05) 50%, rgba(71, 71, 71,0.05) 100%),radial-gradient(circle at center center, hsl(227,81%,21%),hsl(227,81%,21%));
}
.box{
width: 12em;
height: 12em;
position: relative;
background: white;
img{
width: 100%;
height: 100%;
object-fit: cover;
}
svg{
width: 100%;
height: 100%;
position: absolute;
display: block;
top: 0;
left: 0;
}
}
众生所周知,svg是矢量图。所以填充满整个盒子也不会失真。所以我们用绝对定位改在头像上。
现在还看不出来svg起到的任何作用,因为我们还没有写,接下来,我们专心致志的去完成他吧。
2.绘制边框
<svg viewBox="0,0,300,300">
<defs>
<path id="fly-box-path" d="M0 0 L300 0 L300 300 L0 300 Z" fill="none" />
</defs>
<use href="#fly-box-path" stroke-width="12" stroke="#333"></use>
</svg>
我们开始绘制了一个大小为300*300的svg。我们在defs中写入path路径(0,0)->(300,0)->(300,300)->(0,300),即绕着矩形走了一圈,而且切记要让其没有填充色。后面我们通过use去复用这个路径,就可以使用描边了。如果defs不熟悉的同学可以可以把他当做vue中的组件容器,一些可以复用的路径,者动画或者图形等等都可以写入,用过href去引入他,非常的简洁。言归正传,现在我们的外边框就完成了。
3.渐变遮罩
<svg viewBox="0,0,300,300">
<defs>
<path id="fly-box-path" d="M0 0 L300 0 L300 300 L0 300 Z" fill="none" />
<radialGradient id="border-gradient" cx="50%" cy="50%" r="50%" fx="100%" fy="50%" fr="0%">
<stop offset="0%" stop-color="white" />
<stop offset="100%" stop-color="black" />
</radialGradient>
<mask id="fly-box-mask">
<circle r="100" cx="0" cy="0" fill="url(#border-gradient)"></circle>
</mask>
</defs>
<use href="#fly-box-path" stroke-width="12" stroke="#333"></use>
<use href="#fly-box-path" stroke-width="12" stroke="#eff24d" mask="url(#fly-box-mask)"></use>
</svg>
当然我们要出现动画前,先要有个渐变样式,我们可以通过radialGradient去绘制一个圆形渐变,再将他引入到一个在(0,0)点的小球中,当然光这样还不行,还要嵌入遮罩mask,赋予其id。然后我们就可以在外面用mask引入该蒙层使用了,当然别忘了还要再次引入路径。这样我们的起始效果就完成了。
其实就是一个渐变的(0,0)圆球被切开了,在svg边框区域内保留了下来,然后就是现在见到的这样了。
4.飞盒动画
<mask id="fly-box-mask">
<circle r="100" cx="0" cy="0" fill="url(#border-gradient)">
<animateMotion dur="2s" path="M0 0 L300 0 L300 300 L0 300 Z" rotate="auto"
repeatCount="indefinite" />
</circle>
</mask>
估计很多新来的同学还不知道,svg本身是有自己的动画属性,只是兼容有点差强人意。
但我们这次不涉及到IE仅仅使用animateMotion就可以了。dur是持续时间,path是轨迹,rotate设置成auto其实自动改变方向,repeatCount设置为indefinite让他不停的运动。大致就是这样,目的就是让上一步绘制的渐变小球所切的渐变框从(0,0)点沿着动画轨迹不停的在运动。
我们就先说到这吧,发没发现svg很好用有木有,在线演示
结语
相信svg是很多前端新同学的盲区,大家有时间可以学学,挺好玩的,而且也是移动端动画适配的一种重要的解决方案。当然,像这类特效也可以抽离出组件,在我们的开发项目中使用,也是别具特色的。