手把手教你--svg+css3实现炫酷爱心点赞动画

1,485 阅读5分钟

先来看一下最终效果,如下图

一、大爱心的动画实现拆解

1.先使用path路径画爱心,填充色为gray,此时在浏览器上你将看到一个大大的灰心

<svg height="320" width="320" class="like">
    <path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90" fill="gray"/> 
</svg>

         

2.给body一个好看的背景色,使用线性渐变linear-gradient

*{
	margin: 0;
	padding: 0;
}
body {
	background-image:linear-gradient(-10deg, #7028e4 0%, #e5b2ca 100%); 
	width: 100vw;
	height: 100vh;
}

线性渐变,具体的语法这里不讨论,因为篇幅实在太长,请移步获取更详细的信息:

MDN#linear-gradient

3.写心的css样式,先把心居中(绝对定位)

svg.like {
	position: fixed;
	top:calc(50vh - 160px);
	left:calc(50vw -  160px);
}

4.再给心加一个圆框黑色背景色及阴影

svg.like {
	border-radius: 100%;
	background-color: #212121;
	cursor: pointer;
	transform: scale(0.3);
}

                          

5.点击爱心,大爱心动画拆解

  1. 放大爱心

  2. background-color变色(黑色-紫色-品红色)

  3. box-shadow由黑色变黄色

  4. 灰色爱心变白

点击爱心的时候,给body添加一个liked类,再次点击的时候再去掉liked类,

使用classList.toggle

<svg height="320" width="320" class="like" onclick="document.body.classList.toggle('liked')">

在body有liked类的时候才开始动画

.liked svg.like {
	animation:  blink 1s forwards;
}
.liked svg.like path {
	fill:#fff; <!-- 白色 -->
}
@keyframes blink{
	10%{
		transform: scale(.42);
		background-color: #8815b7 ;    <!-- 紫色 -->
		box-shadow: 0 0 250px #f1e794; <!-- 浅黄 -->
	}
	100% {
		background-color: #e01f4f;     <!-- 品红 -->
		box-shadow: 0 0 250px #FFEB3B <!--  柠檬黄 -->
	}
}

此时的效果如下图

二、周围小圆点动画拆解

在点击爱心的时候,即body有likded的时候,这些小圆点才会出现,并从上向四周旋转。所以动画开始后:我们需要在爱心周围 每隔(360/8=45deg)放置一颗圆点,如图:

html如下:

<body>
    <svg height="320" width="320" class="like" onclick="document.body.classList.toggle('liked')">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90" fill="gray"/> 
    </svg>
    <div class="dot dot-1"></div>
    <div class="dot dot-2"></div>
    <div class="dot dot-3"></div>
    <div class="dot dot-4"></div>
    <div class="dot dot-5"></div>
    <div class="dot dot-6"></div>
    <div class="dot dot-7"></div>
    <div class="dot dot-8"></div>
</body>

dot类画圆的样式,dot-1 ~dot-8类调整旋转位置

1.先把这8个白色圆点绝对定位到居中

div.dot {
	width: 12px;
	height: 12px;
	border-radius: 100%;
	background-color: #fff;
	position: fixed;
	top: calc(50vh - 6px);
	left: calc(50vw - 6px);
}

2.使用伪元素,画出上面的另外两个点,细微调整一下大小,使3个点在垂直方向尽量在一条直线上。

div.dot::before {
	content:'';
	position: absolute;
	top:-20px;
	left: 2px;
	width: 8px;
	height: 8px;
	border-radius: 100%;
	background-color: #fff;

}
div.dot::after {
	content:'';
	position: absolute;
	top:-160px;
	left: 1px;
	width: 11px;
	height: 11px;
	border-radius: 100%;
	background-color: #fff;
}

此时,效果如下:

3.动画开始的时候,让3个点整体向上位移100px,并改变非伪元素的颜色为浅蓝色

.liked div.dot {
	transform: translateY(-100px);
	background-color: #00e5ff;
	transition: all 1s;
}

最后,要让3个点渐变消失,加上 opacity:0

.liked div.dot {
    opacity: 0;
}

我们发现,一开始的时候这三个点的看不见的,只有点击后才出现,所以我们给.dot设置一下z-index这个属性为-1

div.dot {
    z-index: -1;
}

这时,我们又发现.dot::after由于太高,没被黑色爱心盖住,怎么办呢?

给.dot::after加上display:none,等动画开始后再让它出现

div.dot::after {
	display: none;
}

body.liked div.dot:after {
	display: block;
}

此时效果为下图:从无到有再到无

4.剩下的,我们只需要安排dot-2 ~dot-8 这 8个点的位置了,相隔45deg。

.liked div.dot-2 {
	transform: rotate(45deg) translateY(-100px);
}
.liked div.dot-3 {
	transform: rotate(90deg) translateY(-100px);
}
.liked div.dot-4 {
	transform: rotate(135deg) translateY(-100px);
}
.liked div.dot-5 {
	transform: rotate(180deg) translateY(-100px);
}
.liked div.dot-6 {
	transform: rotate(225deg) translateY(-100px);
}
.liked div.dot-7 {
	transform: rotate(270deg) translateY(-100px);
}
.liked div.dot-8 {
	transform: rotate(315deg) translateY(-100px);
}

此时,我们看到的效果为:下图

我们需要让颜色opacity:0再爱心归位后再慢慢消失,所以给opacity 延迟1s后在0.5s内过渡执行。

.liked div.dot {
	transition: transform 1s,opacity .5s 1s,background-color .2s .4s;
}

最终效果如下图,小圆点动画完成!

三、大爱心四周8颗爱心的动画

观察到:这8个爱心由中心向四周扩散,4个蓝色爱心在快抵达位置前变成白色并且变大了,最后这8个爱心都消失。

1.先做8个40px的爱心,让它们向像上面的点一样居中并隐藏。

html:

<svg height="40" width="40" viewBox="0 0 320 320" class="h h-1">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="40" width="40" viewBox="0 0 320 320" class="h h-2">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="40" width="40" viewBox="0 0 320 320" class="h h-3">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="40" width="40" viewBox="0 0 320 320" class="h h-4">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>

<svg height="40" width="40" viewBox="0 0 320 320" class="h h-5">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="40" width="40" viewBox="0 0 320 320" class="h h-6">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="40" width="40" viewBox="0 0 320 320" class="h h-7">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="40" width="40" viewBox="0 0 320 320" class="h h-8">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>

css

并且把偶数的爱心设置为蓝色,奇数的设置为黄色

.h {
	position: fixed;
	top:calc(50vh - 20px);
	left: calc(50vw - 20px);
	transform: scale(1);
	z-index: -1;
}
.h:nth-child(odd) {
	fill: skyblue;
}
.h:nth-child(even) {
	fill:yellow;
}

2.动画部分:先让这8个爱心挪到自己应该的位置,根据计算调整margin

.liked .h-1{
	margin-top:-200px;
}
.liked .h-5{
	margin-top:200px;
}
.liked .h-3{
	margin-left:200px;
}
.liked .h-7{
	margin-left:-200px;
}
.liked .h-2{
	margin-top:-140px;
	margin-left:140px;
}
.liked .h-8{
	margin-top:-140px;
	margin-left:-140px;
}
.liked .h-4{
	margin-top:140px;
	margin-left:140px;
}
.liked .h-6{
	margin-top:140px;
	margin-left:-140px;
}

此时的效果为下图:

现在我们就缺给这8个爱心的加上过渡,最后让它们消失

.liked .h {
	opacity: 0;
	transition: margin 1.5s,opacity 0.5s 1.5s;
}

最后给偶数心加上变色和变大,再让这两个效果 延迟1.3s再执行,给margin 自己调整一下

cubic-bezier,可在浏览器里自行调整,找到理想的速度。

.liked .h {
	opacity: 0;
	transition: margin 1.5s cubic-bezier(0.13, 0.7, 0.32, 0.92) ,opacity 0.5s 1.5s,fill 0.2s 1.3s,transform 0.2s 1.3s;
}
.liked .h:nth-child(odd) {	fill: white;
	transform: scale(1.5);
}

可能,此时你需要不断调整动画里的执行时间与延迟时间,来达到你想要的理想效果。

此时,加上上面的小圆点,动画效果为下图:

三、4个蓝色爱心动画

有了上面的经验,这个便很容易了!

1.先搞4个蓝色爱心,给每个爱心110px

<svg height="110" width="110" viewBox="0 0 320 320" class="fly fly-1">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="110" width="110" viewBox="0 0 320 320" class="fly fly-2">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="110" width="110" viewBox="0 0 320 320" class="fly fly-3">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>
<svg height="110" width="110" viewBox="0 0 320 320" class="fly fly-4">
	<path class="path" d="M 160 145 c 15 -90 170 -20 0 90 m 0 -90 c -15 -90 -170 -20 0 90"/>
</svg>

2.让这4个爱心居中并隐藏,给个蓝色!

.fly {
	position: fixed;
	top:calc(50vh - 55px);
	left: calc(50vw - 55px);
	fill: skyblue;
	z-index: -1;
	transform: scale(0.5);
}	

3.先给第一个爱心做动画

.liked .fly-1 {
	animation: fly-1 1s 0.1s;
}
@keyframes fly-1{
	25% {
		margin-top:-100px;
		margin-left:100px;
		transform: scale(0.9);
	}
	50%{
		transform: scale(0.5);
	}
	75%{
		margin-top: 100px;
		margin-left: -100px;
		transform: scale(0.9);
	}
	100%{
		transform: scale(0.5);
	}
}

4.同理搞定其余3个!哈哈

最终完成!完整效果及代码,请戳 

完整效果及代码

更多爱心动画教程即将出炉,欢迎围观!