我用四种方式实现某场所码箭头动画(css3+canvas+svg+js)讲解超详细
大家好!我是猫小白,本期给大家带来一个简单的实战demo,希望大家食用得开心,有收获。==首先声明:此demo存粹为了学习其中的动画知识,请不要用于真实的场景,否则被JC叔叔抓起包吃包住就不应该了瑟!==
此项目基于==成都天府健康通==,其它地区的场所码不知道是否有类似的动画,如果没有也没关系,可以学习下是如何实现的。
为啥子要做这个呢?那是因为有一天我出去买菜,回来保安叔叔恩是要我扫一下场所码,作为一个5星好公民,肯定是非常配合的掏出手机开始扫 。叮~,屏幕上出现一个不挺放大缩小的箭头。我就想,要不用代码来实现一下这个动画吧。
于是就有了这篇文章,我一共是实现了4种方法:
- 第一种,css,零js代码(最简单)
- 第二种,svg,零js代码 (较简单)
- 第三种,js+dom (较复杂)
- 第四种,js+canvas (较复杂)
文章图片
接下来,我们一个一个来分析如何实现的。
准备工作 首先我们假装出去买个菜(未解封的同胞除外例如上海的朋友),回来的时候去保安那里故作镇定,连贯的掏出手机打开天府健康通(成都的哈)扫一下,然后给保安亮一下,不退出界面,淡定回家。
回到家后,拿出手机,打开刚刚的界面,截一个图:
文章图片
加入
html
中,作为div
容器的背景图片,然后我们创建一个白色的框把中间的圆圈和勾遮住,因为我们要自己实现其中的动画效果。实现效果如下:
文章图片
遮板的css代码:
/**遮板**/
.shutter {
position: absolute;
display: block;
width: 120px;
height: 120px;
background-color: #fff;
top: 206px;
left: 150px;
}
核心html代码结构如下,:
只是列举关键的代码,完整代码请到github仓库查看。第一种,css,零js代码 使用
准备工作完成,开始正片!
css3
的animation
动画,可以很容易实现这样的效果,不用一行js代码。单关键是要看明白我们目标动画是由哪些部分组成的,动画是怎么变化的。所以先再次看看这个gif
,注意其中动画部分:文章图片
不难发现:
- 圆圈是由小到大,再由大到小
- 内圈放大到一定程度时,外圈(扩散部分)出现,并且半径不停增大,当内圈放到最大时,扩散圈消失
- 内部的勾也会一起放大缩小,频率和内圈相同
根据上面的规律,我们先实现一个内圈(绿色圈部分)
/**内部圆圈**/
.circle {
position: absolute;
z-index: 9;
width: var(--circle-size);
height: var(--circle-size);
top: 218px;
left: 165px;
background-color: var(--theme-green);
/* background-color: red;
*/
border-radius: 45px;
animation: circleMove 0.7s alternate infinite cubic-bezier(1, 1, 1, 1);
}
--circle-size、--theme-green是我们在开头定义的变量,方便后续使用。
:root {
--theme-green: #4ba776;
/**主题绿色**/
--circle-size: 90px;
/**圆圈大小 宽高一样**/
}
内部圈画好了,还差一个白色的"√",为了简单我直接使用了"√"这个字符串,加入伪类元素的
content
中。你们也可以用图片或者svg。"√"的
css
代码如下:/**内部的勾,使用`.circle`的`before`伪类**/
.circle::before {
z-index: 2;
//z-index要比外圈(阔散圈)大,否则要被背景覆盖
position: absolute;
display: block;
content: "?";
font-size: 63px;
color: #fff;
left: 18px;
top: -1px;
}
让我们预览下现在的效果:
文章图片
哟也~看起来是那么回事了。
现在我们按照内圈相同的颜色和大小,画一个外部圈(扩散圈)。
参考上面的
"√"
的实现,我们用after
伪类来实现:/**动画时外部渐变圈*/
.circle::after {
z-index: 1;
//z-index要比内部的勾小,否则要覆盖掉勾
position: absolute;
display: block;
content: "";
width: calc(var(--circle-size));
height: calc(var(--circle-size));
box-sizing: border-box;
border-radius: 50%;
background-color: #4ba776;
transform: scale(1.2);
/**外圈动画 一轮时间是内圈的2倍 内部圈放大0.7s+缩小0.7s=1.4sinfinite无限重复**/
/* animation: outCircleMove 1.4s infinite cubic-bezier(1, 1, 1, 1);
*/
}
内圈加入放大缩小动画,在
.circle
中计入animation
/**内部圆圈**/
.circle {
position: absolute;
z-index: 9;
width: var(--circle-size);
height: var(--circle-size);
top: 218px;
left: 165px;
background-color: var(--theme-green);
/* background-color: red;
*/
border-radius: 45px;
/*加入放大缩小动画alternate:轮流播放,放大再放小infinite:无限播放ease-in-out:变化函数*/
animation: circleMove 0.7s alternate infinite ease-in-out;
}
/**定义放大缩小动画,最大放大到1.2倍**/
@keyframes circleMove {
0% {
transform: scale(1);
}
100% {
transform: scale(1.2);
}
}
解读:时间设置为0.7s,我们定义了circleMove 动画,意思是在0秒的时候圆圈保持1倍大小,在0.1~0.7s圆圈逐渐变为1.2倍大小。变化的快慢是由【我用四种方式实现某场所码箭头动画(css3+canvas+svg+js)讲解超详细】好内圈动画已经完成,我们来看下效果:animation-timing-function
参数决定的,文中设置的ease-in-out
是进入和退出较慢,中间速度较快的一种变化曲线。
我们可以打开开发者工具,点击animation
属性的曲线图标,查看和选择想要的动画曲线
文章图片
文章图片
perfect!现在我们加入外圈动画,让我们回顾一下:外圈动画是要在内圈放大到一定时间外圈才出现,我们暂定1/5,也就是20%的时候显示并且开始放大(放大对应属性:scale);放大后外圈会越来越便透明,直到内圈放到最大,此时完全透明,感觉像是扩散的效果(透明对应属性:opacity)。
知道这些后,我们设置外圈动画如下:
/*动画时外部渐变圈/
.circle::after {
z-index: 1;
position: absolute;
display: block;
content: "";
width: calc(var(--circle-size));
height: calc(var(--circle-size));
box-sizing: border-box;
border-radius: 50%;
background-color: #4ba776;
/**外圈动画 一轮时间是内圈的2倍 内部圈放大0.7s+缩小0.7s=1.4sinfinite无限重复**/
animation: outCircleMove 1.4s infinite ease-in-out;
}
/**定义扩散圈的放大缩小动画**/
@keyframes outCircleMove {
/**0%~50% 0s~ 0.7s前的时间 此时内圈放大,扩散圈等待时机出现**/
0% {
opacity: 0;
}
/**10% 此时内圈已经放大一段时间, 扩散全显示opacity设为1,倍率为1 **/
10% {
opacity: 1;
transform: scale(1);
}
/**50%到100%是动画0.7s~1.4s的时间 此时内圈缩小,扩散圈变为1.3倍,但是透明度设为0**/
50%,
100% {
transform: scale(1.3);
opacity: 0;
}
}
至此就大功告成了,看下效果:
文章图片
第二种,svg,零js代码 (较简单) 上面了利用css3的动画属性,操作起来非常简单。现在介绍一种用svg动画的方式实现相同的效果。我们知道svg也是有比较丰富的动画特性支持。
我们简单列举一下svg实现动画的几种方法:
1.set
set元素是SVG动画元素中最简单的元素。在经过特定时间间隔后,它只是将属性设置为特定值。因此,形状不会连续进行动画处理,而只是更改属性值一次。2.animate
元素通常放置到一个SVG图像元素里面,用来定义这个图像元素的某个属性的动画变化过程。3.animateMotion
元素也是放置一个图像元素里面,它可以引用一个事先定义好的动画路径,让图像元素按路径定义的方式运动。4.animateTransform
动画上一个目标元素变换属性,从而使动画控制平移,缩放,旋转或倾斜。首先,我们还是拿出上面的基础布局,祖传代码(背景+遮罩)
简单了解过后,我们今天主要用animate
来实现动画。