SVG定义
摘自维基百科:可缩放矢量图形(英语:Scalable Vector Graphics,SVG)是一种基于可扩展标记语言(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-svg在react-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>
);
}
}
项目代码地址
参考资料
svg教程
svg元素
react-native-svg
react-art
SVG Circle Progress
Radial Progress Meters (CSS/SVG)