当前位置:   article > 正文

CanCirPro 使用canvas标签绘制 圆环进度条 有渐变和动画_canwas绘制进度

canwas绘制进度

CanCirPro 使用canvas标签绘制 圆环进度条 有渐变和动画

  1. import React, { Component } from "react";
    import PropTypes from "prop-types";
    
    export default class CanCirPro extends Component {
    
       constructor(props) {
           super(props);
           this.state = {
               percent: 0,
           };
       }
    
       static defaultProps = {
           radius: 45,
           percent: 47.7,
           borderWidth: 6,
           startcolor: '#ffd460',
           centercolor: '#fcc241',
           endColor: '#f79d00',
           textStyle: { fontSize: 11, color: "#fa9a22", textAlign: 'center' },
           openAnimation: true
       }
       static propTypes = {
           radius: PropTypes.number,
           percent: PropTypes.number,
           borderWidth: PropTypes.number,
           startcolor: PropTypes.string,
           centercolor: PropTypes.string,
           endColor: PropTypes.string,
           textStyle: PropTypes.object,
           openAnimation: PropTypes.bool,
       }
       render() {
           return (<div className="cancirproOut" style={{
               width: (this.props.radius + this.props.borderWidth) * 2,
               height: (this.props.radius + this.props.borderWidth) * 2,
           }} >
               <canvas className="cancirproIn" ref={cancirpro => {
                   this.onDraw(cancirpro);//ref时开始绘制
               }}
                   width={(this.props.radius + this.props.borderWidth) * 2} height={(this.props.radius + this.props.borderWidth) * 2}
               />
    
               <div className="cancirproContent" style={{
                   width: (this.props.radius + this.props.borderWidth) * 2,
                   height: (this.props.radius + this.props.borderWidth) * 2,
                   marginTop: - (this.props.radius + this.props.borderWidth) * 2 - this.props.borderWidth/2
               }} >
                   {this.props.children ? this.props.children :
                       <div style={this.props.textStyle}>{this.props.openAnimation ? this.state.percent : this.props.percent}%</div>}
               </div>
    
           </div>);
       }
       componentWillReceiveProps(newprops) {
           this.setState({ percent: 0 });
           this.time = setTimeout(() => {
               this.componentDidMount();
           }, 1);
       }
       componentDidMount() {
           if (this.props.openAnimation) {
               this.startAnimation();
           }
       }
    
       startAnimation() {
           if (this.state.percent < this.props.percent - 2) {
               this.time = setTimeout(() => {
                   this.setState({ percent: this.state.percent + 2 });
                   this.startAnimation();
               }, 11);
           } else {
               this.setState({ percent: this.props.percent });
           }
       }
    
       onDraw(cancirpro) {
           if (cancirpro) {//如果cancirpro存在
    
               let canvas = cancirpro;
               let ctx = canvas.getContext("2d");
               ctx.clearRect(0, 0, (this.props.radius + this.props.borderWidth) * 2, (this.props.radius + this.props.borderWidth) * 2);//清空绘画区域
    
               if (this.props.percent !== 0) {
                   let percent = this.props.openAnimation ? this.state.percent : this.props.percent;
                   let width = (this.props.radius + this.props.borderWidth) * 2;
                   if (window.devicePixelRatio) {
                       canvas.style.width = width + "px";
                       canvas.style.height = width + "px";
                       canvas.height = width * window.devicePixelRatio;
                       canvas.width = width * window.devicePixelRatio;
                       ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
                   }//使用ctx.scale,解决锯齿严重问题
    
                   ctx.beginPath();
                   let grd1 = ctx.createLinearGradient(0, 0, 0, this.props.radius * 2);
                   grd1.addColorStop(0, this.props.startcolor);
                   grd1.addColorStop(1, this.props.centercolor);//线性渐变定义
                   ctx.lineCap = 'round';//连接处圆头
                   ctx.strokeStyle = grd1;//设置strokeStyle为渐变色
                   ctx.lineWidth = this.props.borderWidth;//圆环宽度
    
                   if (percent < 50) {//小于50,绘制前半部分的部分半圆
                       ctx.arc(this.props.radius + this.props.borderWidth, this.props.radius + this.props.borderWidth, this.props.radius, Math.PI * (1.4), Math.PI * (1.4 + percent / 50), false);
                   } else {//大于50,绘制前半部分的完整半圆
                       ctx.arc(this.props.radius + this.props.borderWidth, this.props.radius + this.props.borderWidth, this.props.radius, Math.PI * (1.4), Math.PI * (1.4 + 1), false);
                   }
                   ctx.stroke();
    
    
                   if (percent > 50) {//大于50,才绘制后半部分需要的半圆
                       ctx.beginPath();
                       let grd2 = ctx.createLinearGradient(0, this.props.radius * 2, 0, 0);
                       grd2.addColorStop(0, this.props.centercolor);
                       grd2.addColorStop(1, this.props.endColor);
                       ctx.lineCap = 'round';
                       ctx.strokeStyle = grd2;
                       ctx.lineWidth = this.props.borderWidth;
                       ctx.arc(this.props.radius + this.props.borderWidth, this.props.radius + this.props.borderWidth, this.props.radius, Math.PI * (2.4), Math.PI * (2.4 + ((percent - 50) / 50)), false);
                       ctx.stroke();
                   }
               }
           }
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
  2. .cancirproOut {
       overflow: hidden;
     }
    .cancirproContent {
       display: flex;
       display: -webkit-flex;
       justify-content: center;
       -webkit-justify-content: center;
       align-items: center;
       -webkit-align-items: center;
     }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

qq交流群

​ 179916551 欢迎进群交流前端各种问题

github

https://github.com/1cao2mu/react-circle-progress 如果只是参考思路,也请给个star 谢谢

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/254277
推荐阅读
相关标签
  

闽ICP备14008679号