對react-native-percentage-circle修改,實現圓環旋轉必定角度

最近在項目中要用到[react-native-percentage-circle][1]組件實現進度條和畫圓環。UI界面要實現以下效果

clipboard.png

能夠看出要實現兩個圓環嵌套,實現同心圓仍是比較簡單的,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並不支持直接旋轉

clipboard.png

所以,首先咱們想到可能要用的transform來實現,但實踐發現有各類問題。最後,本人決定是否能夠經過修改源碼實現旋轉效果,對組件的index.js研究發現能夠對組件加上一個props屬性rotate,實現圓環旋轉效果。react

第一步:在PercentageCircle類propTypes中添加一個rotate屬性。

clipboard.png

第二步:在constructor中定義一個新的變量rotate。

clipboard.png

第三步:對if進行修改,要同時修改constructor函數和componentWillReceiveProps()函數

clipboard.png

NOTE:這裏rotate本人未設定值範圍,但建議0-50,若是大於50,失去了意義,能夠經過背景顏色改變,你們在代碼中能夠本身設定rotate的取值範圍。

最後附上本人在git上的Issues的評論,以及index.js代碼git

/** 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-circlegithub

相關文章
相關標籤/搜索