React Native 进度条(react-native-svg)

SVG定义

摘自维基百科可缩放矢量图形(英语:Scalable Vector GraphicsSVG)是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。SVG由W3C制定,是一个开放标准

这些概念性的东西就不多讲了,感兴趣的自行去网络查找,或者参考文章末尾给出的链接。

SVG path 命令

  • M = moveto
  • L = lineto
  • H = horizontal lineto
  • V = vertical lineto
  • C = curveto
  • S = smooth curveto
  • Q = quadratic Bézier curve
  • T = smooth quadratic Bézier curveto
  • A = elliptical Arc
  • Z = closepath

比如:M5 8 L100 0的意思是:
移动到 point(5, 8) → 连线到point(100,0)

我们使用react-native-svgreact-native中实现如下的效果:

进度条效果图

进度条效果图
进度条效果图

直线进度条

<Svg height="24" width="225">
    <G fill="none" stroke="#3d5875">
        <Path strokeLinecap="round" strokeWidth="8" d="M5 8 l215 0" />
    </G>
    <G fill="none" stroke="#00e0ff">
        <Path strokeLinecap="round" strokeWidth="8" d="M5 8 l100 0"/>
    </G>
</Svg>
参数 解释
stroke="#3d5875" 线条的颜色
strokeWidth="8" 线条的宽度
strokeLinecap="round" 线条的两边用圆角
d="M5 8 l215 0" 背景线条充满,总长度225 - 圆角长度5 * 2 = 215
d="M5 8 l100 0" 前景线条的长度
直线进度条效果图

直线进度条 + 动画

// 1,假设进度是0~100
// 2,线条的长度是 215(215 = 225 - 5 * 2)

let AnimatedPath = Animated.createAnimatedComponent(Path);
export default class AwesomeProject extends Component {
    constructor(props)
    {
        super(props);
        this.state = {
            lineFillAnimation: new Animated.Value(0),
        };
        // 这里是动画的映射关系
        this.lineAnimation = this.state.lineFillAnimation.interpolate({
            inputRange: [
               0,
               100
            ],
            outputRange: [
               `M5 8 l0 0`,
               `M5 8 l215 0`,
            ]
         });
    }
    componentDidMount()
    {
        this.startAnimation();
    }
    startAnimation()
    {
        this.state.lineFillAnimation.setValue(0);

        Animated.spring(
            this.state.lineFillAnimation,
            {
                toValue: 50,  // 设置进度值,范围:0~100
                friction: 5,   // 动画摩擦力
                tension: 35 // 动画张力
            }
        ).start();
    }
    render() {
        return (
            <View style={styles.container}>
                <Svg height="16" width="225">
                    <G fill="none" stroke="#3d5875">
                        <Path strokeLinecap="round" strokeWidth="8" d="M5 8 l215 0" />
                    </G>
                    <G fill="none" stroke="#00e0ff">
                        <AnimatedPath strokeLinecap="round" strokeWidth="8" d={this.lineAnimation}/>
                    </G>
                </Svg>
            </View>
        );
    }
}
直线进度条+动画效果
直线进度条+动画效果

圆形进度条

this.dasharray = [Math.PI * 2 * 42];

<Svg
    height="100"
    width="100">
    <Circle
        cx="50"
        cy="50"
        r="42"
        stroke="#3d5875"
        strokeWidth="8"
        fill="transparent"
    />
    <Circle
        cx="50"
        cy="50"
        r="42"
        origin="50,50"
        rotate="-90"
        stroke="#00e0ff"
        strokeWidth="8"
        strokeLinecap="round"
        fill="transparent"
        strokeDasharray={this.dasharray} strokeDashoffset={50}
    />
</Svg>
参数 解释
<Svg height="100" width="100" 整个圆形画布的长、宽为100x100
<Circle cx="50" cy="50"
strokeWidth="8"
r="42"
stroke="#3d5875"
fill="transparent" />
画底色圆形
圆形的中心点是point(50,50)
线条宽是8
半径是42 = (100 - 8 * 2) / 2
线条颜色是#3d5875
圆形的填充色是透明
rotate="-90" 逆时针旋转90度
strokeLinecap="round" 线条的结点是圆形的
strokeDasharray 固定的计算形式:圆周长 = [Math.PI * 2 * 半径]
strokeDashoffset={50} 前景色的周长度,就是图中黑色的弧形的长度(范围:0~圆周长)
圆形进度条

圆形进度条 + 动画

let AnimatedCircle = Animated.createAnimatedComponent(Circle)

export default class AwesomeProject extends Component {
    constructor(props)
    {
        super(props);
        this.state = {
            circleFillAnimation: new Animated.Value(0)
        };
        this.dasharray = [Math.PI * 2 * 42];
        // 这里是动画的映射关系
        this.circleAnimation = this.state.circleFillAnimation.interpolate({
            inputRange: [
               0,
               100,
            ],
            outputRange: [
                this.dasharray[0],
                0
            ]
         });
    }
    componentDidMount()
    {
        this.startAnimation();
    }
    startAnimation()
    {
        this.state.circleFillAnimation.setValue(0);
        Animated.spring(
            this.state.circleFillAnimation,
            {
                toValue: 80,  // 设置进度值,范围:0~100
                friction: 5,     // 动画摩擦力
                tension: 35   // 动画张力
            }
        ).start();
    }
    render() {
        return (
            <View style={styles.container}>
                <Svg
                    height="100"
                    width="100">
                    <Circle
                        cx="50"
                        cy="50"
                        r="42"
                        stroke="#3d5875"
                        strokeWidth="8"
                        fill="transparent"
                    />
                    <AnimatedCircle
                        cx="50"
                        cy="50"
                        r="42"
                        origin="50,50"
                        rotate="-90"
                        stroke="#00e0ff"
                        strokeWidth="8"
                        strokeLinecap="round"
                        fill="transparent"
                        strokeDasharray={this.dasharray} strokeDashoffset={this.circleAnimation}
                    />
                </Svg>
            </View>
        );
    }
}
圆形进度条+动画
圆形进度条+动画

项目代码地址

react-native-svg-example

参考资料

svg教程
svg元素
react-native-svg
react-art
SVG Circle Progress
Radial Progress Meters (CSS/SVG)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容