【问题标题】:How to create a CSS spinning loading animation?如何创建 CSS 旋转加载动画?
【发布时间】:2022-01-05 03:10:10
【问题描述】:

我想创建一个 css(或 JS)加载动画,如图所示:

应该有一个容器矩形,它有一个类。然后应该将一些 css 应用于该矩形,以便有一些覆盖。首先它是全黑的,透明度为 50%。然后随着时间的推移,黑色随着顺时针旋转而减少,直到不再有黑色。如果我给它一个值100,它应该是全黑的,如果我给它0,它应该没有黑色,并且完全显示底层图像。

有人知道任何教程或如何创建它吗?

【问题讨论】:

    标签: javascript html css animation loading


    【解决方案1】:

    无疑是困难的,但也是可能的。经过大约一个小时的打磨,我想出了很多 div 和一些工作代码:

    const inner = document.getElementById('inner');
    const black = document.getElementById('black');
    const cover = document.getElementById('cover');
    const overlay = document.getElementById('overlay');
    const block = document.getElementById('block');
    inner.addEventListener('animationend', e => {
      inner.style.display = 'none';
      block.style.display = 'block';
    });
    cover.addEventListener('animationend', e => {
      alert('done!');
    });
    #wrapper {
      height: 100px;
      width: 100px;
      border: 5px solid black;
      position: relative;
      overflow: hidden;
    }
    
    #wrapper > div {
      position: absolute;
      height: 300%;
      width: 300%;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    #cover {
      background-color: white;
      animation: spin 5s linear 5s forwards;
    }
    #overlay {
      background-color: black;
      width: 50%;
      height: 100%;
      position: absolute;
      left: 0;
      top: 0;
    }
    
    #inner {
      animation: spin 5s linear forwards;
    }
    #black {
      background-color: black;
      width: 50%;
      height: 100%;
      position: absolute;
      right: 0;
      top: 0;
    }
    
    @keyframes spin {
      from {
        transform: translate(-50%, -50%) rotate(0);
      }
      to {
        transform: translate(-50%, -50%) rotate(180deg);
      }
    }
    
    #block {
      display: none;
      background-color: white;
      height: 100%!important;
      width: 50%!important;
      transform: translate(0, 0)!important;
      position: absolute;
      top: 0!important;
      right: 0!important;
      z-index: 10
    }
    
    /*Just for the demo*/
    body, html {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100%;
    }
    <div id="wrapper">
      <div id="cover">
        <div id="overlay"></div>
      </div>
      <div id="inner">
        <div id="black"></div>
      </div>
      <div id="block"></div>
    </div>

    这到底是如何工作的? 考虑这张图片(对不起,糟糕的图形):

    中间的小方块代表#wrapper。它周围较大的正方形是它的孩子#inner。在#inner(带有条纹)的右侧是#black,它占据了其父级的一半。 #inner 旋转 180 度,消失,然后 #cover 在另一侧基本上做同样的事情。 #block 阻止 #cover 的黑色部分显示在另一侧。 *哇*,太有趣了!

    【讨论】:

    • 哇,你真是个天才!您将如何使用 JS 代码重新启动动画?有没有办法暂停/恢复?
    • 这是一个非常好的解决方案,但还有一个小问题是当我将它们设置为 50% 的透明度时(如上所述),它们相互重叠并且相交部分变得更加坚固。最好它们都是 50% 透明的。
    • @omega 想到的最简单的方法是删除内部元素并重新添加它们或弄乱类名;见stackoverflow.com/questions/6268508/…。我不确定你所说的透明度是什么意思。将它们设置为 25%?
    • 谢谢。我使用画布为每一帧绘制一个多边形来解决这个问题。也添加了我的版本。看看这个。而且由于它是基于 JS 的,我可以通过透明度控制速度和暂停/恢复/重启。
    • @omega 太棒了!我想无论如何它更容易。我只是以为你希望它是元素和 DOM ?。
    【解决方案2】:

    我是用画布想出来的。

    var canvas = document.getElementById('loading_animation');
    var ctx = canvas.getContext('2d');
    ctx.fillStyle = '#00000088';
    
    var final = [];
    var list1 = [
        [Math.floor(canvas.width / 2), 0],
        [Math.floor(canvas.width / 2), Math.floor(canvas.height / 2)]
    ];
    var list2 = [
        [canvas.width - 1, 0],
        [canvas.width - 1, canvas.height - 1],
        [0, canvas.height - 1],
        [0, 0]
    ];
    var last = [Math.floor(canvas.width / 2), 0];
    
    for (var x = Math.floor(canvas.width / 2); x < canvas.width; x += 1) {
        var path = list1.concat([[x, 0]]).concat(list2).concat([last]);
        final.push(path);
    }
    list2.shift();
    for (var y = 1; y < canvas.height; y += 1) {
        var path = list1.concat([[canvas.width - 1, y]]).concat(list2).concat([last]);
        final.push(path);
    }
    list2.shift();
    for (var x = canvas.width - 2; x >= 0; x -= 1) {
        var path = list1.concat([[x, canvas.height - 1]]).concat(list2).concat([last]);
        final.push(path);
    }
    list2.shift();
    for (var y = canvas.height - 2; y >= 0; y -= 1) {
        var path = list1.concat([[0, y]]).concat(list2).concat([last]);
        final.push(path);
    }
    list2.shift();
    for (var x = 1; x < Math.floor(canvas.width / 2); x += 1) {
        var path = list1.concat([[x, 0]]).concat(list2).concat([last]);
        final.push(path);
    }
    function RenderAnimation() {
        var path = final.shift();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.beginPath();
        ctx.moveTo(path[0][0], path[0][1]);
        for (let i = 1; i < path.length; i++) {
            ctx.lineTo(path[i][0], path[i][1]);
        }
        ctx.closePath();
        ctx.fill();
        if (final.length > 0) {
            window.requestAnimationFrame(RenderAnimation);
        } else {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
        }
    }
    
    RenderAnimation();
        <!DOCTYPE html>
        <html>
        
        <head>
            <title>Title of the document</title>
            <style>
                canvas {
                    background-image: url('https://media.wired.com/photos/5d09594a62bcb0c9752779d9/125:94/w_1994,h_1500,c_limit/Transpo_G70_TA-518126.jpg');
                    background-size: 100% 100%;
                    background-repeat: no-repeat;
                }
            </style>
        </head>
        
        <body>
            <canvas id="loading_animation" width="300px" height="200px"></canvas>
        </body>
        
        </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      相关资源
      最近更新 更多