CSS3实现loading效果

2023-05-16

前言

晚上躺床上刷视频的时候看到有个前端大佬写了一个loading,这是效果:

loading

感觉也挺有意思哈,要不自己也写一个,学习 + 复习 两不误。

但是又因为太晚了,不想起来开整,那就留到第二天空了再整。第二天借中午休息这点时间来完成头天晚上立下的falg,最后再通过这篇笔记来记录一下里面的一些知识点。

结构

看他这个视频,css部分采用的是less写的,刚好我有个平时用来实现一些项目功能或者自己感兴趣的一个react 搭建的模板,然后就在这个基础上创建了个页面来实现这个loading效果。

废话不多说,开整。

html

<div className='wrp'>
	<div className='loading'>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	    <div className='dot'></div>
	</div>
</div>

最底层子节点共计36个,按照一圈360°来讲,正好每个分10°,便于计算,没啥特别的意义,可以根据自己的喜好需求来定义到底可以展示多少个。

css

@ballSize: 10px;
@containerSize: 150px;
@ballNum: 36;
@pdeg: 10deg;
@ani-duration: 2000ms;

.wrp {
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgb(105, 207, 247);

    .loading {
        width: @containerSize;
        height: @containerSize;
        // border: 1px solid #fff;
        border-radius: 50%;
        position: relative;

        .dot {
            position: absolute;
            top: 50%;
            left: 50%;
            width: @ballSize;
            height: @ballSize;
            margin-left: -@ballSize/2;
            margin-top: -@ballSize/2;
            // background-color: red;
            perspective: 70px;
            transform-style: preserve-3d;

            &::before,&::after{
                content: '';
                width: 100%;
                height: 100%;
                border-radius: 50%;
                position: absolute;
            }
            &::before{
                background-color: #000;
                top: -100%;

                // 重要 -- 动画
                animation: moveBlack @ani-duration infinite;
            }
            &::after{
                background-color: #fff;
                top: 100%;

                // 重要 -- 动画
                animation: moveWhite @ani-duration infinite;
            }
        }


        // 重要 -- 循环
        .loop(@i) when (@i <=@ballNum) {
            .dot:nth-child(@{i}) {
                transform: rotate(@pdeg * (@i - 1)) translateY(-@containerSize/2);
                color: red;

                // 重要 -- 动画延时
                &::before,&::after{
                    animation-delay: -@ani-duration / @ballNum * 6 * @i;
                }
            }
        
            .loop(@i + 1);
        }
        
        .loop(1);


    }
}

// 重要 -- 沿着Y轴旋转
@keyframes moveBlack {
    0%{
        animation-timing-function: ease-in;
    }
    25%{
        transform: translate3d(0, 100%, @ballSize);
        animation-timing-function: ease-out;
    }
    50%{
        transform: translate3d(0, 200%, 0);
        animation-timing-function: ease-in;
    }
    75%{
        transform: translate3d(0, 100%, -@ballSize);
        animation-timing-function: ease-out;
    }
}


// 重要 -- 沿着Y轴旋转
@keyframes moveWhite {
    0%{
        animation-timing-function: ease-in;
    }
    25%{
        transform: translate3d(0, -100%, -@ballSize);
        animation-timing-function: ease-out;
    }
    50%{
        transform: translate3d(0, -200%, -0);
        animation-timing-function: ease-in;
    }
    75%{
        transform: translate3d(0, -100%, @ballSize);
        animation-timing-function: ease-out;
    }
}

知识点总结

  1. 定位

    • 绝对定位:relative
    • 相对定位:absolute
  2. 伪元素

    ::before和::after是伪元素

    需要注意的是CSS3中为了与伪类做区别,伪元素采用双冒号的写法;但因为兼容性的问题,所以现在大部分还是统一的单冒号,比如 :first-line、:first-letter、:before、:after 等,CSS3中引入的伪元素不允许用单冒号这种写法。

  3. less定义变量

    @ballSize: 10px;

    参照上面的示例,左侧以@开头,紧跟着定义的变量名称,右侧则是声明变量所对应的值,最后需要跟上分好(可以根据自己的需求进行配置)。

  4. 循环

    // 重要 -- 循环
    .loop(@i) when (@i <=@ballNum) {   
    
        // 循环事件中函数需要处理的主体
        .dot:nth-child(@{i}) {
            transform: rotate(@pdeg * (@i - 1)) translateY(-@containerSize/2);
            color: red;
    
            // 重要 -- 动画延时
            &::before,
            &::after {
                animation-delay: -@ani-duration / @ballNum * 6 * @i;
            }
        }
    
        // 类似于JavaScript中的递归
        .loop(@i + 1);
    }
    
    // 先调用一次
    .loop(1);
    
    • .loop 可以理解为一个函数名,这个名称是任意的
    • @i 是传递进去的参数
    • when 类似于 JavaScript 中的 if 判断关键字
    • when (@i <=@ballNum) 括号里面的是判断条件,可以理解为 if (i <= ballNum) { // 执行具体事件 } 这样子的判断执行语句
    • @ballNum 此处的值为36,判断边界
  5. 动画

    • 动画名称
    animation-name: moveBlack;
    // 指定要绑定到选择器的关键帧的名称
    
    • 动画执行时间
    animation-duration: 2000ms;
    
    // or
    
    animation-duration: 2s;
    // 动画指定需要多少秒或毫秒完成
    
    • 动画执行方式
    animation-timing-function:linear;
    

    animation-timing-function使用的数学函数,称为三次贝塞尔曲线,速度曲线。使用此函数,您可以使用您自己的值,或使用预先定义的值之一:

    描述
    linear动画从头到尾的速度是相同的。
    ease默认。动画以低速开始,然后加快,在结束前变慢。
    ease-in动画以低速开始。
    ease-out动画以低速结束。
    ease-in-out动画以低速开始和结束。
    steps(int,start|end)指定了时间函数中的间隔数量(步长)。有两个参数,第一个参数指定函数的间隔数,该参数是一个正整数(大于 0)。 第二个参数是可选的,表示动画是从时间段的开头连续还是末尾连续。含义分别如下:start:表示直接开始。 end:默认值,表示戛然而止。
    cubic-bezier(n,n,n,n)在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。
    • 动画执行延时时间
    animation-delay: 6s
    
    • 动画执行周期
    animation-iteration-count:3;
    

    animation-iteration-count属性定义动画应该播放多少次。

    描述
    n一个数字,定义应该播放多少次动画
    infinite指定动画应该播放无限次(永远)
  6. @keyframes
    要创建 CSS 动画,您首先需要了解 @keyframes 规则,@keyframes 规则用来定义动画各个阶段的属性值,类似于 flash 动画中的关键帧,语法格式如下:

@keyframes animationName {
    from {
        width: 100px;
    }
    to {
        width: 200px;
        // 里面可以设置任意的样式
    }
}
// 或者
@keyframes animationName {
    0% {
        width: 100px;
    }
    50% {
        width: 200px;
    }
    // 中间还可以添加其他百分比点位进行设置
    100% {
        width: 300px;
        // 里面可以设置任意的样式
    }
}

语法说明如下:

  • animationName:表示动画的名称;
  • from:定义动画的开头,相当于 0%;
  • to:定义动画的结尾,相当于 100%;

最后说明一下,这份笔记并不全面,仅仅是对这个loading效果所用到的一些属性做了一些记录,如果还想深入了解,可以再查查资料进行系统的了解学习。

文中如果讲的有问题的地方还请评论区多多指教。

最后再说一句,如果对三维感觉很迷茫,不如多看看下面这两张图,然后对照代码多多思考。

正常情况

在这里插入图片描述
换个角度再看看

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CSS3实现loading效果 的相关文章