SVG超简单实现豆瓣loading动画

这段时间在豆瓣上看有什么剧的时候,发现豆瓣的loading动画还挺棒的。因此决定模仿着来写一个。css

效果图

我经过CSS3配合SVG来完成此次模仿豆瓣的loading动画。没用过SVG的也不用慌,我下面会写出相应的属性方便你去理解。由于这个真的超简单。那么咱们就直奔主题吧html

初始化svg

咱们须要先完成一个静态的笑脸浏览器

始化SVG视图的大小bash

<svg width="100" height="100"></svg>
复制代码

我指定了一个宽高都为100px的区域,width=”100”width=”100px”是等价的。svg

画嘴巴

咱们把嘴巴给画出来,在svg内先画一个圆函数

<circle class="mouth" cx="50" cy="50" r="14"></circle>
复制代码

cxcy 属性定义圆点的 xy 坐标。动画

看到浏览器上面多了一个填充的黑色圆点spa

原型

接下来咱们给咱们的嘴巴加上css样式3d

.mouth {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 44, 44;
    transform-origin: center;   /* transform动画时以自身中心做为基点 */
}
复制代码

对应的属性调试

css属性 说明 此处
fill 填充颜色 none(不填充)
stroke 轮廓的颜色 #00B51D
stroke-width 轮廓的宽度 5
stroke-linecap 开放路径两端的形状 round
stroke-dasharray 建立虚线 44, 44
transform-origin 旋转元素的基点位置 center(自身中心)

这里重点讲一下stroke-dasharray,它的属性值可为none<dasharray>inherit

<dasharray>它是一个<length><percentage>数列,数与数之间用逗号或者空白隔开,指定短划线和缺口的长度。

一个参数时: 实际上是表示虚线长度和每段虚线之间的间距
两个参数或者多个参数时:一个表示长度,一个表示间距

  • stroke-dasharray = '10' 表示:虚线长10,间距10,而后重复 虚线长10,间距10
  • stroke-dasharray = '10, 5' 表示:虚线长10,间距5,而后重复 虚线长10,间距5
  • stroke-dasharray = '20, 10, 5' 表示:虚线长20,间距10,虚线长5,接着是间距20,虚线10,间距5,以后开始如此循环

根据圆的周长公式L=2πr,圆的半径r=14,因此L=87.96452≈88,那么咱们取虚线长度为44,间距44作一条虚线,恰好就是圆周长的一半。

可见此时咱们的嘴巴部分已经完成了

原型

画眼睛

接下来开始画眼睛,我又画了一个circle

<circle class="eye" cx="50" cy="50" r="14"></circle>
复制代码

原型

咱们依然能够经过stroke-dasharray来画出一对眼睛

先把嘴巴注释掉,避免影响咱们调试。

stroke-dasharray的虚线长度为0的时,则能够获得无数个点状的圆。根据上面圆的周长公式咱们能够获得周长为88,那么咱们每1/4个长度就为22,此时咱们再把间距调整为66。此时两个点的垂直距离恰好为90度

接下来咱们给咱们的眼睛加上css样式

.eye {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 0, 66;
}
复制代码

原型

为了让嘴巴对齐,咱们左旋转45度,给eye加上transform属性

transform-origin: center;
transform: rotate(-45deg);
复制代码

原型

这样子咱们就完成了眼睛

加动画

通过我无数遍慢放(一帧一帧)的观察豆瓣的加载动画,终于找到了规律(哭)。

嘴巴动画

加动画效果,这也是最激动的一步,咱们先来看下嘴巴部分

原型

经过动画咱们能够看出嘴巴部分是旋转了两圈的,而且在旋转第一圈的时候,两边的间距缩小为1/4,在第二圈的时候,间距恢复为1/2,且最后有一段的停留时间

根据最后的一段停留时间旋转两圈

咱们能够经过transform完成,简单

@keyframes mounthAni {
    80%, 100% {
        transform: rotate(720deg);
    }
}
复制代码

第一圈的时候两边间距缩小为1/4,也就是此时stroke-dasharray的值为 44, 22,后续再恢复为1/2

@keyframes mounthAni {
    40% {
        stroke-dasharray: 44, 22;   /* 间距改成1/4 */
    }
    80%, 100% {
        stroke-dasharray: 44, 44;   /* 间距恢复为1/2 */
        transform: rotate(720deg);
    }
}
复制代码

动画的运行速度为开始快,结束慢,因此咱们使用ease-out做为贝塞尔曲线函数值

这样嘴巴的动画就完成了

眼睛动画

原型

一样的,经过动画咱们能够看出眼睛部分一样是旋转了两圈,而且在旋转第一圈的时候,两边的间距增大为7/8,在第二圈的时候,间距恢复为3/4,且最后有一段的停留时间

@keyframes eyeAni {
    40% {
        stroke-dasharray: 0, 77;    /* 间距改成7/8 */
    }
    80%, 100% {
        transform: rotate(675deg);  /* 间距恢复为3/4 */
        stroke-dasharray: 0, 66;
    }
}
复制代码

动画的运行速度为开始和结束慢,因此咱们使用ease-in-out做为贝塞尔曲线函数值

至此咱们的眼睛动画也就完成了

咱们把两个动画整合起来,这样就完成了模仿豆瓣的loading动画了,特简单。

效果图

源码

html

<svg width="100" height="100">
    <circle class="mouth" cx="50" cy="50" r="14"></circle>
    <circle class="eye" cx="50" cy="50" r="14"></circle>
</svg>
复制代码

css

.mouth {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 44, 44;
    transform-origin: center;   /* transform动画时以自身中心做为基点 */
    animation: mounthAni 2.3s ease-out infinite;
}

.eye {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 0, 66;
    transform-origin: center;
    transform: rotate(-45deg);
    animation: eyeAni 2.3s ease-in-out infinite;
}

@keyframes mounthAni {
    40% {
        stroke-dasharray: 44, 22;   /* 间距改成1/4 */
    }
    80%, 100% {
        stroke-dasharray: 44, 44;   /* 间距恢复为1/2 */
        transform: rotate(720deg);
    }
}

@keyframes eyeAni {
    40% {
        stroke-dasharray: 0, 77;    /* 间距改成7/8 */
    }
    80%, 100% {
        transform: rotate(675deg);  /* 间距恢复为3/4 */
        stroke-dasharray: 0, 66;
    }
}
复制代码

总结

CSS3动画已足够强大,可是若是要实现上面那种间距可变大变小的动画效果,只用CSS的话我仍是没有想到怎么实现,若是各位有方法的话欢迎评论告诉我😀,因此使用了SVGCSS来完成,眼睛部分本来想过使用animateMotion来完成,奈何看了半天仍是不会用🤣,因此就想着只用CSS的动画效果完成了此次的动画,没想到意外的简单,因此把方法分享给你们。整个loading动画都围绕着stroke-dasharray展开,用到的SVG属性真的是冰山一角,上面的内容若是有什么错误的话还望各位多多指教。

相关文章
相关标签/搜索