实现 10 个 React 的 Loading 组件

508 阅读4分钟

1. 正方形"滚动"加载

image.png

组件

import React from 'react';
import './index.scss';

function Loading() {
  return (
    <div className="boxLoading"></div>
  );
}

export default React.memo(Loading);

样式

/* loading.css */
.boxLoading {
  width: 50px;
  height: 50px;
  margin: auto;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

.boxLoading:before {
  content: '';
  width: 50px;
  height: 5px;
  background: #fff;
  opacity: 0.7;
  position: absolute;
  top: 59px;
  left: 0;
  border-radius: 50%;
  animation: shadow .5s linear infinite;
}

.boxLoading:after {
  content: '';
  width: 50px;
  height: 50px;
  background: #e04960;
  animation: animate .5s linear infinite;
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 3px;
}

@keyframes animate {
  17% {
    border-bottom-right-radius: 3px;
  }

  25% {
    transform: translateY(9px) rotate(22.5deg);
  }

  50% {
    transform: translateY(18px) scale(1, .9) rotate(45deg);
    border-bottom-right-radius: 40px;
  }

  75% {
    transform: translateY(9px) rotate(67.5deg);
  }

  100% {
    transform: translateY(0) rotate(90deg);
  }
}

@keyframes shadow {

  0%,
  100% {
    transform: scale(1, 1);
  }

  50% {
    transform: scale(1.2, 1);
  }
}

2.方块消失术加载

image.png

组件

import React from 'react';
import './index.scss';

function Loading() {
  return (
    <div className="sk-cube-grid">
      <div className="sk-cube sk-cube-1"></div>
      <div className="sk-cube sk-cube-2"></div>
      <div className="sk-cube sk-cube-3"></div>
      <div className="sk-cube sk-cube-4"></div>
      <div className="sk-cube sk-cube-5"></div>
      <div className="sk-cube sk-cube-6"></div>
      <div className="sk-cube sk-cube-7"></div>
      <div className="sk-cube sk-cube-8"></div>
      <div className="sk-cube sk-cube-9"></div>
    </div>
  );
}

export default React.memo(Loading);

样式

/* loading.css */
.sk-cube-grid {
  width: 4em;
  height: 4em;
  margin: auto;
}

.sk-cube {
  width: 33%;
  height: 33%;
  background-color: #e04960;
  float: left;
  animation: sk-cube-grid-scale-delay 1.3s infinite ease-in-out;
}

.sk-cube-1 {
  animation-delay: 0.2s;
}

.sk-cube-2 {
  animation-delay: 0.3s;
}

.sk-cube-3 {
  animation-delay: 0.4s;
}

.sk-cube-4 {
  animation-delay: 0.1s;
}

.sk-cube-5 {
  animation-delay: 0.2s;
}

.sk-cube-6 {
  animation-delay: 0.3s;
}

.sk-cube-7 {
  animation-delay: 0s;
}

.sk-cube-8 {
  animation-delay: 0.1s;
}

.sk-cube-9 {
  animation-delay: 0.2s;
}

@keyframes sk-cube-grid-scale-delay {

  0%,
  70%,
  100% {
    transform: scale3D(1, 1, 1);
  }

  35% {
    transform: scale3D(0, 0, 1);
  }
}

3.填充正方形加载

image.png

组件

import React from 'react';
import './index.scss';

function Loading() {
  return (
    <div style={{ margin: "50px auto" }}>
      <span className="loading">
        <span className="loading-inner"></span>
      </span>
    </div>

  );
}

export default React.memo(Loading);

样式

/* loading.css */
.loading {
  display: inline-block;
  width: 30px;
  height: 30px;
  position: relative;
  border: 4px solid #e04960;
  animation: loader 4s infinite ease;
}

.loading-inner {
  vertical-align: top;
  display: inline-block;
  width: 100%;
  background-color: #e04960;
  animation: loader-inner 4s infinite ease-in;
}

@keyframes loader {
  0% {
    transform: rotate(0deg);
  }

  25% {
    transform: rotate(180deg);
  }

  50% {
    transform: rotate(180deg);
  }

  75% {
    transform: rotate(360deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

@keyframes loader-inner {
  0% {
    height: 0%;
  }

  25% {
    height: 0%;
  }

  50% {
    height: 100%;
  }

  75% {
    height: 100%;
  }

  100% {
    height: 0%;
  }
}

4.音浪加载

image.png

import React from 'react';
import './index.scss';

function Loading() {
  return (
    <div class="loader">
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
  );
}

export default React.memo(Loading);

css样式

/* loading.css */
.loader {
  position: absolute;
  top: 0px;
  bottom: 0px;
  left: 0px;
  right: 0px;
  margin: auto;
  width: 175px;
  height: 100px;
}

.loader span {
  display: block;
  background: #e04960;
  width: 7px;
  height: 100%;
  border-radius: 14px;
  margin-right: 5px;
  float: left;
}

.loader span:last-child {
  margin-right: 0px;
}

.loader span:nth-child(1) {
  animation: load 2.5s 1.4s infinite linear;
}

.loader span:nth-child(2) {
  animation: load 2.5s 1.2s infinite linear;
}

.loader span:nth-child(3) {
  animation: load 2.5s 1s infinite linear;
}

.loader span:nth-child(4) {
  animation: load 2.5s 0.8s infinite linear;
}

.loader span:nth-child(5) {
  animation: load 2.5s 0.6s infinite linear;
}

.loader span:nth-child(6) {
  animation: load 2.5s 0.4s infinite linear;
}

.loader span:nth-child(7) {
  animation: load 2.5s 0.2s infinite linear;
}

.loader span:nth-child(8) {
  animation: load 2.5s 0s infinite linear;
}

.loader span:nth-child(9) {
  animation: load 2.5s 0.2s infinite linear;
}

.loader span:nth-child(10) {
  animation: load 2.5s 0.4s infinite linear;
}

.loader span:nth-child(11) {
  animation: load 2.5s 0.6s infinite linear;
}

.loader span:nth-child(12) {
  animation: load 2.5s 0.8s infinite linear;
}

.loader span:nth-child(13) {
  animation: load 2.5s 1s infinite linear;
}

.loader span:nth-child(14) {
  animation: load 2.5s 1.2s infinite linear;
}

.loader span:nth-child(15) {
  animation: load 2.5s 1.4s infinite linear;
}

@keyframes load {
  0% {
    background: #531430;
    transform: scaleY(0.08);
  }

  50% {
    background: #e04960;

    transform: scaleY(1);
  }

  100% {
    background: #531430;
    transform: scaleY(0.08);
  }
}

5.声浪加载

image.png

import React from 'react';
import './index.scss';

function Loading() {
  return (
    <div class="bars">
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
      <div className="bar"></div>
    </div>
  );
}

export default React.memo(Loading);

样式

/* loading.css */
.bars {
  height: 30px;
  left: 50%;
  margin: -30px 0 0 -20px;
  position: absolute;
  top: 60%;
  width: 40px;
}

.bar {
  background: #e04960;
  bottom: 1px;
  height: 3px;
  position: absolute;
  width: 3px;
  animation: sound 0ms -800ms linear infinite alternate;
}

@keyframes sound {
  0% {
    opacity: .35;
    height: 3px;
  }

  100% {
    opacity: 1;
    height: 28px;
  }
}

.bar:nth-child(1) {
  left: 1px;
  animation-duration: 474ms;
}

.bar:nth-child(2) {
  left: 5px;
  animation-duration: 433ms;
}

.bar:nth-child(3) {
  left: 9px;
  animation-duration: 407ms;
}

.bar:nth-child(4) {
  left: 13px;
  animation-duration: 458ms;
}

.bar:nth-child(5) {
  left: 17px;
  animation-duration: 400ms;
}

.bar:nth-child(6) {
  left: 21px;
  animation-duration: 427ms;
}

.bar:nth-child(7) {
  left: 25px;
  animation-duration: 441ms;
}

.bar:nth-child(8) {
  left: 29px;
  animation-duration: 419ms;
}

.bar:nth-child(9) {
  left: 33px;
  animation-duration: 487ms;
}

.bar:nth-child(10) {
  left: 37px;
  animation-duration: 442ms;
}

6.loading 字符

image.png

import React from 'react';
import './index.scss';

function Loading() {
  return (
    <div style={{ marginTop: "100px" }}>
      <div className="wavy">
        <span className='bar'>l</span>
        <span className='bar'>o</span>
        <span className='bar'>a</span>
        <span className='bar'>d</span>
        <span className='bar'>i</span>
        <span className='bar'>n</span>
        <span className='bar'>g</span>
        <span className='bar'>.</span>
        <span className='bar'>.</span>
        <span className='bar'>.</span>
      </div>
    </div>

  );
}

export default React.memo(Loading);

样式

.wavy {
  /* 相对定位 */
  position: relative;
  /* 倒影效果 */
  -webkit-box-reflect: below -12px linear-gradient(transparent, rgba(0, 0, 0, 0.2));
}

.wavy span {
  position: relative;
  display: inline-block;
  color: #e04960;
  font-size: 50px;
  text-transform: uppercase;
  letter-spacing: 8px;
  animation: load 2s ease-in-out infinite;
  /* 通过var函数调用自定义属性--i,再计算出动画延迟时间 */
  // animation-delay: calc(0.2s * var(--i));
}

/* 定义动画 */
@keyframes load {
  0% {
    transform: translateY(0);
  }

  20% {
    transform: translateY(-20px);
  }

  40%,
  100% {
    transform: translateY(0);
  }
}

.bar:nth-child(1) {
  animation-delay: 0.2s
}

.bar:nth-child(2) {
  animation-delay: 0.4s
}

.bar:nth-child(3) {
  animation-delay: 0.6s
}

.bar:nth-child(4) {
  animation-delay: 0.8s
}

.bar:nth-child(5) {
  animation-delay: 1.0s
}

.bar:nth-child(6) {
  animation-delay: 1.2s
}

.bar:nth-child(7) {
  animation-delay: 1.4s
}

.bar:nth-child(8) {
  animation-delay: 1.6s
}

.bar:nth-child(9) {
  animation-delay: 1.8s
}

.bar:nth-child(10) {
  animation-delay: 2.0s
}