如何制作 CSS 旋转加载动画?

How to create a CSS spinning loading animation?

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

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

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

无疑是困难的,但有可能。经过大约一个小时的磨合,我想出了很多 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。它周围较大的正方形是它的 child #inner。在 #inner 的右侧(带条纹)是 #black,它占据了 parent 的一半。 #inner 旋转 180 度,消失,然后 #cover 在另一侧基本上做同样的事情。 #block#cover 的黑色部分不显示在另一边。 *哇*,真有趣!

我用 canvas 弄明白了。

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>