对react-native-percentage-circle修改,实现圆环旋转一定角度
最近在项目中要用到[react-native-percentage-circle][1]组件实现进度条和画圆环。UI界面要实现如下效果
可以看出要实现两个圆环嵌套,实现同心圆还是比较简单的,react-native-percentage-circle组件支持子元素,所以,在外面圆环里面嵌套一个同心圆环,然后设置样式就行了。具体代码如下:
<PercentageCircle radius={70} percent={100} color={'#ffffff'} bgcolor={"#ffffff"} innerColor={"#ffffff"} borderWidth={8}>
<View style={{flex:1,justifyContent:'center',alignItems: 'center',}}>
<PercentageCircle radius={60} percent={49} rotate={10} bgcolor={'#ff912f'} color={"#ffac48"} innerColor={"#ffffff"} borderWidth={15}>
<Text style={{fontFamily: "MicrosoftYaHei",fontSize: 22,lineHeight: 27,color: "#545453"}}> 1990笔</Text>
</PercentageCircle>
</View>
</PercentageCircle>
然而要实现里面圆环旋转就有点难度了,首先目前该组件最新版本v1.0.6并不支持直接旋转
因此,首先我们想到可能要用的transform来实现,但实践发现有各种问题。最后,本人决定是否可以通过修改源码实现旋转效果,对组件的index.js研究发现可以对组件加上一个props属性rotate,实现圆环旋转效果。
第一步:在PercentageCircle类propTypes中添加一个rotate属性。
第二步:在constructor中定义一个新的变量rotate。
第三步:对if进行修改,要同时修改constructor函数和componentWillReceiveProps()函数
NOTE:这里rotate本人未设定值范围,但建议0-50,如果大于50,失去了意义,可以通过背景颜色改变,大家在代码中可以自己设定rotate的取值范围。
最后附上本人在git上的Issues的评论,以及index.js代码
/** React Native Percentage Circle
** @github https://github.com/JackPu/react-native-percentage-circle
** React Native Version >=0.25
** to fixed react native version
**/
import React, {
Component
} from 'react';
import {
StyleSheet,
View,
Text,
} from 'react-native';
const styles = StyleSheet.create({
circle: {
overflow: 'hidden',
position: 'relative',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#e3e3e3',
},
leftWrap: {
overflow: 'hidden',
position: 'absolute',
top: 0,
},
rightWrap: {
position: 'absolute',
},
loader: {
position: 'absolute',
left: 0,
top: 0,
borderRadius: 1000,
},
innerCircle: {
overflow: 'hidden',
position: 'relative',
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 11,
color: '#888',
},
});
class PercentageCircle extends Component {
propTypes: {
color: React.PropTypes.string,
bgcolor: React.PropTypes.string,
innerColor: React.PropTypes.string,
radius: React.PropTypes.number,
percent: React.PropTypes.number,
borderWidth: React.Proptypes.number,
textStyle: React.Proptypes.array,
disabled: React.PropTypes.bool,
rotate: React.Proptypes.number, //定义旋转角度
}
constructor(props) {
super(props);
let percent = this.props.percent;
let leftTransformerDegree = '0deg';
let rightTransformerDegree = '0deg';
//初始化值
let rotate = this.props.rotate;
if (typeof rotate == 'undefined') {
rotate = 0;
}
if (percent >= 50) {
//rightTransformerDegree = '180deg';
//leftTransformerDegree = (percent - 50) * 3.6 + 'deg';
rightTransformerDegree = 180 + rotate * 3.6 + 'deg';
leftTransformerDegree = (percent + rotate - 50) * 3.6 + 'deg';
} else {
//rightTransformerDegree = percent * 3.6 + 'deg';
rightTransformerDegree = (percent + rotate - 50) * 3.6 + 'deg';
leftTransformerDegree = rotate * 3.6 + 'deg';
}
this.state = {
percent: this.props.percent,
borderWidth: this.props.borderWidth < 2 || !this.props.borderWidth ? 2 : this.props.borderWidth,
leftTransformerDegree: leftTransformerDegree,
rightTransformerDegree: rightTransformerDegree,
textStyle: this.props.textStyle ? this.props.textStyle : null
};
}
componentWillReceiveProps(nextProps) {
let percent = nextProps.percent;
let leftTransformerDegree = '0deg';
let rightTransformerDegree = '0deg';
/*
if (percent >= 50) {
rightTransformerDegree = '180deg';
leftTransformerDegree = (percent - 50) * 3.6 + 'deg';
} else {
rightTransformerDegree = '0deg';
leftTransformerDegree = -(50 - percent) * 3.6 + 'deg';
}
*/
//初始化值
let rotate = this.props.rotate;
if (typeof rotate == 'undefined') {
rotate = 0;
}
if (percent >= 50) {
//rightTransformerDegree = '180deg';
//leftTransformerDegree = (percent - 50) * 3.6 + 'deg';
rightTransformerDegree = 180 + rotate * 3.6 + 'deg';
leftTransformerDegree = (percent + rotate - 50) * 3.6 + 'deg';
} else {
//rightTransformerDegree = percent * 3.6 + 'deg';
rightTransformerDegree = (percent + rotate - 50) * 3.6 + 'deg';
leftTransformerDegree = rotate * 3.6 + 'deg';
}
this.setState({
percent: this.props.percent,
borderWidth: this.props.borderWidth < 2 || !this.props.borderWidth ? 2 : this.props.borderWidth,
leftTransformerDegree: leftTransformerDegree,
rightTransformerDegree: rightTransformerDegree
});
}
render() {
if (this.props.disabled) {
return (
<View style={[styles.circle,{
width:this.props.radius*2,
height: this.props.radius*2,
borderRadius:this.props.radius
}]}>
<Text style={styles.text}>{this.props.disabledText}</Text>
</View>
);
}
return (
<View style={[styles.circle,{
width:this.props.radius*2,
height: this.props.radius*2,
borderRadius:this.props.radius,
backgroundColor: this.props.bgcolor
}]}>
<View style={[styles.leftWrap,{
width: this.props.radius,
height: this.props.radius * 2,
left:0,
}]}>
<View style={[styles.loader,{
left: this.props.radius,
width:this.props.radius,
height: this.props.radius*2,
borderTopLeftRadius:0,
borderBottomLeftRadius:0,
backgroundColor:this.props.color,
transform:[{translateX:-this.props.radius/2},{rotate:this.state.leftTransformerDegree},{translateX:this.props.radius/2}],
}]}></View>
</View>
<View style={[styles.leftWrap,{
left:this.props.radius,
width: this.props.radius,
height: this.props.radius * 2,
}]}>
<View style={[styles.loader,{
left:-this.props.radius,
width:this.props.radius,
height: this.props.radius*2,
borderTopRightRadius:0,
borderBottomRightRadius:0,
backgroundColor: this.props.percent < 50 ? this.props.bgcolor : this.props.color,
transform:[{translateX:this.props.radius/2},{rotate:this.state.rightTransformerDegree},{translateX:-this.props.radius/2}],
}]}></View>
</View>
<View style={[styles.innerCircle,{
width:(this.props.radius - this.state.borderWidth)*2,
height:(this.props.radius - this.state.borderWidth)*2,
borderRadius:this.props.radius - this.state.borderWidth,
backgroundColor: this.props.innerColor,
}]}>
{this.props.children ? this.props.children :
<Text style={[styles.text, this.state.textStyle]}>{this.props.percent}%</Text>}
</View>
</View>
);
}
}
// set some attributes default value
PercentageCircle.defaultProps = {
bgcolor: '#e3e3e3',
innerColor: '#fff'
};
module.exports = PercentageCircle;
s://github.com/JackPu/react-native-percentage-circle