React 写一个 spinner 圆形加载动画

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:这里我们还缺 spinner 的样式,我们这里创建一个高阶组件更好的扩充我们的 spinner。然后就可以看到最开始的动画效果了
  • 最近业务和设计稿需要需要写一个加载的动画,然后就决定构建一个 react 的 spinner 圆圈:o:️旋转的加载动画。
  • 关键Key : react,css3 clip-path

先来看看需要实现的效果

React 写一个 spinner 圆形加载动画

css3 clip path

  • 这里我们来了解一下 clip-path 的使用方法,最开始这个属性是 clip 然后最近改用了 clip-path.

兼容性

  • 首先看看浏览器适配问题
  • 不支持IE和Firefox,支持webkit浏览器。注意,在现代浏览器中需要使用-webkit-前缀。

使用方法

/* Geometry values */
clip-path: inset(100px 50px);
clip-path: circle(50px at 0 100px);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);

/* Box and geometry values combined */
clip-path: padding-box circle(50px at 0 100px);
复制代码

一些 demo

  • 预览
    • React 写一个 spinner 圆形加载动画
<div className="demo">
    <h4>三角裁剪</h4>
    <div className="clipClass1" />
    <h4>圆形裁剪</h4>
    <div className="clipClass2" />
    <h4>椭圆裁剪</h4>
    <div className="clipClass3" />
    <h4>裁剪插图</h4>
    <div className="clipClass4" />
</div>
复制代码
.demo > div {
  width: 100px;
  height: 100px;
  margin: 20px;
  background: lightcoral;
}
.clipClass1 {
  -webkit-clip-path: polygon(0 100%, 50% 0, 100% 100%);
  clip-path: polygon(0 100%, 50% 0, 100% 100%);
}

.clipClass2 {
  -webkit-clip-path: circle(50% at 50% 50%);
  clip-path: circle(50% at 50% 50%);
}

.clipClass3 {
  -webkit-clip-path: ellipse(30% 20% at 50% 50%);
  clip-path: ellipse(30% 20% at 50% 50%);
}

.clipClass4 {
  -webkit-clip-path: inset(25% 0 25% 0 round 0 25% 0 25%);
  clip-path: inset(25% 0 25% 0 round 0 25% 0 25%);
}
复制代码

构建加载动画组件

  • 目录

    • src
      • index.js
      • help.tsx
      • spinner.tsx
      • style.css
  • spinner.tsx

import React, { Component } from "react";
import PropTypes from "prop-types";

/**
 * @desc 加载动画组件
 * @param
 *      size: 半径大小
 *      spinnerColor: 颜色
 *      spinnerWidth: 圆圈宽度
 *      visible: 是否显示
 */
export interface ISpinnerProps {
  size?: number;
  spinnerColor?: string;
  spinnerWidth?: number;
  visible?: boolean;
}

class Spinner extends Component<ISpinnerProps> {
  static defaultProps = {
    size: 40,
    spinnerColor: "#333333",
    spinnerWidth: 5,
    visible: true
  };

  render() {
    const { visible } = this.props;
    if (!visible) {
      return null;
    }

    const { id, size, width, height, spinnerColor, spinnerWidth } = this.props;
    const dimension = size || Math.min(width, height);
    return (
      <div
        id={id}
        className="spinner"
        style={{
          width: dimension,
          height: dimension,
          borderColor: spinnerColor,
          borderWidth: spinnerWidth
        }}
      />
    );
  }
}

export default Spinner;

复制代码

这里我们还缺 spinner 的样式,我们这里创建一个高阶组件更好的扩充我们的 spinner。

  • help.tsx
    • 关键点 clip-path: polygon 动画
    • animation、transform 动画的使用
import React from "react";

const css = `
.spinner {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  border: 10px solid #333;
  box-sizing: border-box;
  // animation: 动画名 动画时长 动画速度曲线 轮流反向播放动画(alternate) 循环次数(infinite)
  animation: sweep 1s linear alternate infinite, rota 0.8s linear infinite;
}

// 其他浏览器支持 @-webkit-等 这里为了节省空间就不加了,需要支持
@keyframes rota {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}


@keyframes sweep {
  0% {
    clip-path: polygon(0% 0%, 0% 0%, 0% 0%, 50% 50%, 0% 0%, 0% 0%, 0% 0%);
  }
  50% {
    clip-path: polygon(0% 0%, 0% 100%, 0% 100%, 50% 50%, 100% 0%, 100% 0%, 0% 0%);
  }
  100% {
    clip-path: polygon(0% 0%, 0% 100%, 100% 100%, 50% 50%, 100% 100%, 100% 0%, 0% 0%);
  }
}
`;

const SPINNER_ID = "spinner_id_style";

const ID_HOLDER = {};
ID_HOLDER.id = 0;

export const SpinnerMixin = Component =>
  class extends React.Component {
    constructor(props) {
      super(props);

      // 在 head 中插入上面的样式
      if (!document.getElementById(SPINNER_ID)) {
        const head = document.head || document.getElementsByTagName("head")[0];
        const sprc = document.createElement("style");
        sprc.id = SPINNER_ID;
        sprc.type = "text/css";
        if (sprc.styleSheet) {
          sprc.styleSheet.cssText = css;
        } else {
          sprc.appendChild(document.createTextNode(css));
        }
        if (head) {
          head.appendChild(sprc);
        }
      }

      //加上唯一 id 区分多个 spinner
      ID_HOLDER.id += 1;
      this.state = {
        id: `spinner_${ID_HOLDER.id}`
      };
    }

    render() {
      return <Component {...this.props} {...this.state} />;
    }
  };

复制代码
  • 最后

  • spinner.tsx

    • 包裹上我们的高阶组件,然后再引用就 ok 了
import React, { Component } from "react";
import PropTypes from "prop-types";
import { SpinnerMixin } from "./help";

// ...... some codes

export default SpinnerMixin(Spinner);

复制代码
  • index.js
import React from "react";
import ReactDOM from "react-dom";
import Spinner from "./spinner";

function App() {
  return (
    <div className="App">
      <h1>Hello Clip-Path</h1>

      <div className="container">
        <h4>加载动画</h4>
        <Spinner
          spinnerColor="red"
          spinnerWidth={10}
          size={100}
          visible={true}
        />
      </div>
     
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

复制代码

然后就可以看到最开始的动画效果了

React 写一个 spinner 圆形加载动画

参考


以上所述就是小编给大家介绍的《React 写一个 spinner 圆形加载动画》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

无线:网络文化中激进的经验主义

无线:网络文化中激进的经验主义

[英] 阿德里安·麦肯齐 / 张帆 / 上海译文出版社 / 2018-9

本书研究了无线是如何成为当代人类经验的主角的。从路由器、智能电话、电子书、城市到在线工作、服务协议、玩具以及国家等各个方面,人们已经感觉到了无线技术所引发的变革。本书作者援引一个世纪之前的哲学技术来分析当代最前沿的后网络时代的人类状况。基于威廉•詹姆斯的实用主义哲学相关的彻底经验主义,作者提出了把失序的无线网络世界与人们的感知匹配起来的新方式。一起来看看 《无线:网络文化中激进的经验主义》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试