使用div不借助任何画图框架画环形图,其实很简单

今天遇到一个问题,就是页面上有许多环形图,而且功能只需要展示比例而已,这个时候如果引用一些图表框架的话,那可能会让页面加载速度变慢,毕竟这些图表框架都不小。

所以我就想用几个DIV,再加一些CSS3的属性,希望能够解决这个问题,并且能够适配所有的PC或移动的浏览器。搜索了一些资料,有说使用css3 clip的属性,但是Opera和UC For Android是不支持这个属性的。

然后。。。突发灵感,想到了一个很变态的方法。废话不多说,先贴代码。

React 组件代码
class Circle extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      index: 0
    };
  }

  componentDidMount() {
    let rootHeight = this.root.clientHeight / 2 + 'px';
    this.rule.style.borderRightWidth = rootHeight;
    this.cover.style.borderRightWidth = rootHeight;

    this.draw(360);
  }

  /**
   * 画环形图
   * @param {Number} 角度的值
   */
  draw(deg) {
    if (deg < 0) {
      deg = 0;
    }

    if (deg > 360) {
      deg = 360;
    }

    if (deg < 180) {
      this.cover.className = this.cover.className.replace(/add/, 'cover');

      this.rotate(deg);
    } else {
      this.cover.className = this.cover.className.replace(/cover/, 'add');

      this.rotate(deg - 180);
    }
  }

  /**
   * 旋转
   * @param {Number} 旋转的角度
   */
  rotate(deg) {
    let ele = this.cover;
    let degStr = `rotate(${deg}deg)`;
    ele.style.webkitTransform = degStr;
    ele.style.MozTransform = degStr;
    ele.style.msTransform = degStr;
    ele.style.OTransform = degStr;
    ele.style.transform = degStr;
  }

  render() {
    let { className } = this.props;

    return (
      <div
        ref={ root => (this.root = root) }
        className={ 'circle ' + (className || '') }
      >
        <div ref={ rule => (this.rule = rule) } className="rule" />
        <div ref={ cover => (this.cover = cover) } className="rule cover" />

        <div className="outter">
          <div className="inner">{this.props.children}</div>
        </div>
      </div>
    );
  }

 

CSS代码
.circle {
  margin: 120px 60px;
  border-radius: 50%;
  height: 120px;
  width: 120px;
  position: relative;
  background-color: #fff;
  overflow: hidden;

  .rule {
    position: absolute;
    height: 100%;
    width: 100%;
    border-radius: 50%;
    border-bottom: 0px;
    border-left: 0px;
    border-top: 0;
    border-right: 30px solid red;

    &.cover {
      border-right-color: #fff;
    }

    &.add {
      border-right-color: red;
    }
  }

  .outter {
    position: absolute;
    left: 2px;
    right: 2px;
    top: 2px;
    bottom: 2px;
    border-radius: 50%;
    background-color: #000;
    text-align: center;
  }
}

 

实现的中心思想是利用border属性,设置其上下做都为0,然后设置右宽度为容器高度的一般,再设置为环形指示的颜色,然后再加一个相同的设置的同级div,但设置其颜色为白色,通过旋转白色的div来控制显示的数值,当角度超过180时,则将该白色的div设置背景色为环形指示的颜色,再旋转角度-180.

比较另类的解决思路,最后得到以下的效果。

关键字:DIV画曲线,DIV画扇形,环形图,饼图