位图是将图像的所有像素信息进行记录,而矢量图形只记录形成图像的公式,渲染时才进行像素计算。因此,一般位图的文件大小比矢量图形大。
位图可以记录非常复杂的图像信息,而矢量图形记录相对有限;位图缩放会影响图像的质量,但矢量图形不会,两者各有优点。
SVG包含基本形状、渐变、常用滤镜和动画,使用描述性语言xml来表述图形。
react-native-svg是react-native第三方库,目前还不支持滤镜及内置动画。为描述方便,下文提及SVG均指react-native-svg。
基本形状:
· 矩形 <rect>
· 圆形 <circle>
· 椭圆 <ellipse>
· 线 <line>
· 折线 <polyline>
· 多边形 <polygon>
· 路径 <path>
· 文本 <text>
通过这些基本形状的组装变化,可以繁衍出更复杂的形状。
公共属性:
· fill 形状的填充色
· fillOpacity 形状的透明度
· stroke 外边框颜色
· strokeWidth 外边框的宽度
· strokeOpacity 外边框的透明度
· strokeLinecap 外边框端点的样式
· strokeLinejoin 外边框拐角线的样式
· strokeDasharray 外边框虚线和间隔的样式
· strokeDashoffset 外边框虚线的间隔
· x 横坐标
· y 纵坐标
· rotate 旋转角度
· scale 缩放
· origin 当前对象的基坐标
· originX 当前对象的基坐标X
· originY 当前对象的基坐标Y
基本示例:
<Rect x="20" y="20" width="75" height="75"/>
渐变是一种从一种颜色到另一种颜色的平滑过渡。
SVG支持两种变换:线性变换
和放射性变换
。
线性渐变:
放射性渐变:
svg基本形状均支持以下事件:
• disabled
• onPress
• onPressIn
• onPressOut
• onLongPress
• delayPressIn
• delayPressOut
• delayLongPress
SVG没有内置动画属性,因此动画效果需要手动实现(手动需要每次重新绘制SVG组件,因此性能上先天不足)。
path是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状。但是使用起来没有直接使用其他形状简单直接,只有在基本形状无法满足的情况下,才考虑使用path。
示例:
<path d="M250 150 L150 350 L350 350 Z" />
path有个重要的属性d
,其属性值是一系列操作路径的命令,格式为命令+参数
的序列:
• 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
通过这些指令,可以自定义任何形状,满足绘图需求。
指令分类:
- 移动坐标M
- 画线LHV
- 贝赛尔曲线CSQT
- 弧形A
- 闭合路径Z
就像拿笔在纸上作画一样,首先将笔移动到起点位置,然后绘制线条。为了方便绘制线条,将线条抽象为几类模型:直线、曲线。曲线又分为贝塞尔曲线和弧形曲线。
- 直线:L是绘制直线,H是绘制水平直线,V绘制垂直直线。
- 曲线:C是三次贝塞尔曲线,Q是二次贝赛尔曲线,ST是CQ简单控制方式。
- 弧形:A通过指定椭圆的半径及切线控制弧形(这种方式不容易理解)。
先看效果图:
该示例包含几个部分:
SVG是绘图系统,因此,动画中的所有元素都需要手动计算坐标,不能依赖RN的自动布局。SVG的坐标是以左上角为起点。
动画中文本有居中对齐、左对齐和右对齐,Text元素有个属性:textAnchor
可以设置对齐方式。
中心圆作为背景,不需要动画,只需设置Circle中心点及半径即可。
Path元素中有A属性可做弧形设计。这里我们对弧形填充色为透明色,边框设大一点就是圆弧的效果。有两个需要注意的地方:
- 弧形使用半径及起始点来确定中心点,弧形的中心点与背景圆的中心点要重合
- 边框放大,端点是直角不是圆角,需要设置属性
strokeLinecap="round"
由于SVG没有自带动画,因此要实现码表动画,只能刷新重绘实现动画效果。结合RN使用,就是将弧形坐标作为变量,放到state中,再起个定时器更新弧形坐标。
弧形有个属性需要动态控制,才嫩实现需要的效果:large-arc-flag
,它代表取长弧还是短弧,因为动画过程中,开始是长弧,然后越来越小。
SVG给每个元素赋予了事件绑定,因此只需设置onPress
事件完成用户操作即可。
- 未优化状态(帧率50): cpu为120%左右
- 优化状态(帧率50,动态计算常量化): cpu loading不变
- 减少帧率(帧率23) cpu为40%左右
由此可见,动态计算部分几乎不占用cpu资源,降低帧率可以节省部分cpu资源。性能不高的主要原因:
- SVG没有内置动画,重绘效率低下
- SVG不能局部绘制(即背景部分每次刷新时不需要重新绘制)
针对svg不支持局部绘制,我们可以采用曲线方案,即采用双层或多层svg重叠来达到局部绘制的相似效果
。具体操作:将背景圆、圆弧以及文本作为底部图形,将动画圆弧作为前景svg,这样只刷新前景svg即可。
- 按照此方案release状态下,cpu占用不到20%
结论:SVG目前不适合做永久动画,做间断动画还算满足需求。
lottie-react-native (待技术预言),简单了解该动画库比较强悍,但是不支持动画交互操作,可用范围下降不少。