赞
踩
CanCirPro 使用canvas标签绘制 圆环进度条 有渐变和动画
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();
}
}
}
}
}
.cancirproOut {
overflow: hidden;
}
.cancirproContent {
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
}
179916551 欢迎进群交流前端各种问题
https://github.com/1cao2mu/react-circle-progress 如果只是参考思路,也请给个star 谢谢
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。