持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情
前些天第一次做大屏,要搞个像下面这样的水球图,有两种实现方式,第一种就是使用CSS3中的animation,第二种就是使用Echarts的 echarts-liquidfill 插件。
CSS3 animation
先看看使用CSS实现的效果
可以看到整体实现效果差强人意,下面是实现的思路。 首先,在结构上,其实是外部div.outter包含一个内部div.inner,然后通过将outter设为相对定位relative,inner设为绝对定位absolute,使得inner的一半位于outter的上方。
接着,实现效果使用的是animation,通过给inner添加旋转动画,使得inner动起来,最后给outter设置overflow为hidden,将inner溢出的部分隐藏起来,就完成了。
上面是实现的思路,接着我们根据思路来实现需求。
<div class="outter">
<div class="inner"></div>
</div>
@keyframes toRotate {
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}
.outter {
background-color: rgb(231, 101, 101);
width: 200px;
height: 200px;
border-radius: 50%;
position: relative;
overflow: hidden;
}
.inner {
width: 250px;
height: 250px;
background-color: #021b41;
position: absolute;
border-radius: 40% 35% 40% 45%;
top: -120px;
animation: toRotate 10s linear -5s infinite;
}
通过上面的代码,我们可以实现下面的效果
我们只需要将inner的背景色调的和后面的背景色一样,就算是基本完成了。接下来是实现过程中所用到的一些知识点。
animation
如上图,animation有8个子属性,其中我们比较常用的有 animation-delay,animation-direction,animation-duration,animation-iteration-count,animation-name,animation-timing-function 这5个。
keyframes
使用animation定义完动画时间后,我们要先使用keyframes来定义动画序列。就是我们要使用 @keyframe 动画序列名称 来建立两个或者两个以上关键帧来实现。
每一个关键帧都描述了动画元素在给定的时间点上应该如何渲染。
比如说,我们给一个正方形div定义了一个10s的旋转动画,那么我们要通过@keyframes来定义,第一秒的时候,这个div要旋转多少度,第二秒要旋转多少度,当然,并不需要每一秒都详细写出来。 关键帧关键帧,我们只需要写整个动画中关键的那几帧就可以了,比如说,整个动画10s,那你第五秒可能要旋转个180度了才合理吧。
关键帧并不是通过直接写1s,2s这样来描述时间,而是通过百分比来指定动画发生的时间点。 0%表示动画发生的第一刻,100%则表示动画的最后一刻。因为0%和100%是两个比较特殊的时刻,因此它们还有别名:0%的别名是from,100%的别名是to。
@keyframes myAnimaion {
0% {
background-color: red;
}
100% {
background-color: black;
}
}
/* 上下两种写法等价 */
@keyframes myAnimaion {
from {
background-color: red;
}
to {
background-color: black;
}
}
除了上述的两个关键帧之外,也可包含额外可选的关键帧,描述动画开始和结束之间的状态。
@keyframes myAnimaion {
0% {
background-color: red;
}
30% {
background-color: yello;
}
70% {
background-color: green;
width:100px
}
100% {
background-color: black;
}
}
animation-delay
单位
该属性的单位是秒s或者毫秒ms,在定义的时候,一定要带上单位,否则定义无效。
默认值
该属性的默认值是0s,也就是说立即开始执行动画。
除了0s,定一个负值也会让动画立即执行,不同的是,动画会从动画序列中的某个位置开始执行,比如说-1s,则会从动画序列的第1s开始执行。
animation-direction
这个属性定义了动画结束后是否反向播放,一共有4个可选值
| 值 | 含义 |
|---|---|
| normal(默认值) | 每个循环内动画向前循环,换言之,每个动画循环结束,动画重置到起点重新开始 |
| alternate | 动画交替反向运行,反向运行时,动画按步后退,同时,带时间功能的函数也反向,比如,ease-in 在反向时成为 ease-out。计数取决于开始时是奇数迭代还是偶数迭代 |
| reverse | 反向运行动画,每周期结束动画由尾到头运行。 |
| alternate-reverse | 反向交替,反向开始交替。动画第一次运行时是反向的,然后下一次是正向,后面依次循环。决定奇数次或偶数次的计数从 1 开始。 |
animation-duration
一个动画的周期时长。
单位
该属性的单位是秒s或者毫秒ms,不带单位无效。
默认值
该属性的默认值是0s,表示无动画。
负值也会无效,不过早期的一些浏览器会将负值当作0s。
animation-iteration-count
定义动画在结束前运行的次数。
如果指定了多个值,每次播放动画时,将使用列表中的下一个值,在使用最后一个值后循环回第一个值。
如果值为infinite,则为无限循环播放。
如果值为Number,则循环播放对应次数,默认值为1。值可以是小数, 比如说0.5,表示播放到动画周期的一半。
值不可以是负值。
animation-name
animation-name属性指定应用的一系列动画,每个名称代表一个由 @keyframes 定义的动画序列。这里说的是一系列,也就是说可以是多个值。
@keyframes myBox_length {
from {
width: 100px;
}
25% {
width: 200px;
}
75% {
width: 300px;
}
to {
width: 400px;
}
}
@keyframes myBox_color {
from {
background-color: red;
}
25% {
background-color: green;
}
75% {
background-color: blue;
}
to {
background-color: black;
}
}
比如我上面定义了两个动画序列,分别控制背景色和长度,可以通过animation-name来指定动画元素使用这两个动画序列,被指定的动画序列是同时执行的。
animation-name: myBox_length,myBox_color ;
transform
transform允许我们旋转、倾斜或平移给定元素。它只能转换由盒模型定位的元素,即 display:block 的元素。
transform的值可以是一个或者多个CSS变换函数,变换函数按从左到右的顺序相乘,这意味着复合变换按从右到左的顺序有效地应用。比如我们这里用到的变换函数rotate。
transform变换函数贼多,这里不展开了。
rotate(a)
这个函数可以在元素不变形的情况下,旋转元素,如果参数值a是整数,则顺时针旋转,如果是负数,则逆时针旋转。
单位可以是deg。
上面这些就是通过CSS实现水球图的知识点了,如果都理解了相信应该也能自己实现水球图了。这种实现方式的一个缺点就是,top属性的值和百分比的关系比较难对应,就是说,我们通过改变top属性的值,来改变水球中水的量多少,但是我们不同情况下水球的宽高又不固定,很难知道top应该变成多少才能代表50%这样。
Echarts-liquidfill
后来,需求改了,说昨天做的大屏作废,给了个新的原型图,还是有水球图(下图),但是更加复杂了,只好借别人的轮子来用了(主要是累了,不想努力了)。
水球图这东西,Echarts中有,但是它不在实例中,而是在插件中。
安装依赖
首先在Vue项目中安装以下两个依赖
npm install echarts --save
npm install echarts-liquidfill --save
这里要注意上面两个依赖的版本,我的是Echarts5和对应的EchartsLiquidFill3,不同版本的引入方法会有些区别。
我们来到要引入水球图的组件中,写下如下两行代码:
import * as echarts from "echarts";
import "echarts-liquidfill";
然后在 template 中写好DOM结构
<template>
<div id="app">
<div id="liquidFill">
<!-- 水球图容器 -->
</div>
</div>
</template>
记得给水球图的容器设置宽高,我这里是将宽高写在了style标签里面。
然后开始初始化,完整代码如下:
代码来自于CSDN的这位大哥:岁末Zzz
下面是效果图
还得是别人的轮子用着舒服啊。