在移动应用的开发过程中,绘制基本的二维图形或动画是必不可少的。然而,考虑到Android和iOS均有一套各自的API方案,因此采用一种更普遍接受的技术方案,更有利于代码的双平台兼容。
art 是一个旨在多浏览器兼容的Node style CommonJS模块。在它的基础上,Facebook又开发了 react-art ,封装art,使之可以被react.js所使用,即实现了前端的svg库。然而,考虑到react.js的JSX语法,已经支持将 cirle>
`<svg>`等等svg标签直接插入到dom中(当然此时使用的就不是react-art库了)此外还有HTML canvas的存在,因此,在前端上,react-art并非不可替代。
然而,在移动端,考虑到跨平台的需求,加之web端的技术积累,react-art成为了现成的绘制图形的解决方案。react-native分别在0.10.0和0.18.0上添加了iOS和Android平台上对react-art的支持,当然,没有文档。在文档基本等于没有的情况下,笔者苦逼地翻源代码,为大家带来了(全球首发?=_=)的入门文档。
推荐大家采用react-art自带的Example: Vector-Widget 。React.js和React-Native的区别,只在于下文所述的ART获取上,然后该例子就可以同时应用在Web端和移动端上了。
package.json中需要引入art库,笔者的版本设置是 art: ^0.10.0
。
var React = require('react-native'); var ReactART = React.ART;
或者使用ES6的Destructuring特性:
var { ..., ART, ..., } = React;
var React = require('react'); var ReactART = React.ART;
接下来的所述的代码,web端和移动端都是通用的,这也是React Native的诱惑所在。
var { Shape, Group, Transform, Surface, ..., } = React.ART;
所有的svg component必须被一个Surface标签所包含。Props如下:
width: Surface的宽度。
height: Surface的高度。
style: margin系列和padding系列都生效。
Group用于组合art component。比如在一个函数中返回多个svg component的情况,此时就必须要用/<Group/>包一下,否则即报错。/<Group/>可以嵌套使用。
style:margin和padding系列均无效,我怀疑不接受style。
function _render() { return ( <Group> <Shape d={"M160 160 A 45 45, 0, 0, 1, 115 205"} stroke="#000000" strokeWidth={3} /> <Shape d={"M160 160 A 45 45, 0, 0, 1, 115 205"} stroke="#000000" strokeWidth={3} /> </Group> ); }
Shape用于生成路径,语法与svg中的<path>很相似。Shape的Props如下:
d: 语法与svg规范相同
stroke: 线条颜色,"#FFFFFF"的形式
strokeWidth: 线条宽度,{3}的形式
transform:接受 new ART.Transform()生成的object,具体见下文Transform条目。
语法更近似于移动端。使用方法:
var ReactART = require('./ReactART'); var Path = ReactART.Path; function _render() { // 除close以外的所有方法都返回修改后的自身,因此支持链式调用 var path = Path().moveTo(0, -radius) .arc(0, radius * 2, radius) .arc(0, radius * -2, radius) .close(); // path可以直接赋值给d return <Shape d={path} /> }
可以看到,取出的Path是一个构造函数。Path对象的中的函数功能如下,大多与svg规范一致,我就再啰嗦一遍了。svg规范中<path>的d属性请参见 https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d :
push():
reset(): 清空Path
move(x, y): 等同于'm',移动到目的坐标,参数x和y是相对目标下的目的坐标
moveTo(x, y): 等同于'M',与move只差别在x和y是绝对坐标。
line(x, y): 等同于'l',从一个坐标点到另一个坐标点画直线,参数x和y是相对坐标下的目的坐标
lineTo(x, y): 等同于'L',与line只差别在x和y是绝对坐标。
arc(x, y, rx, ry, outer): 等同于'a',从一个坐标点向另一个坐标点画椭圆曲线,x和y是相对坐标下的目的坐标,rx和ry是椭圆的长轴半径和短轴半径,outer只有0和1两个数字,代表是大角度还是小角度。
arcTo(x, y, rx, ry, outer): 等同于'A',与arc只差别在x和y是绝对坐标。
curve(2个,4个或6个参数): 从一个坐标点向另一个坐标点画贝塞尔曲线。
当参数为两个时,等同于't',绘制光滑二次贝塞尔曲线。
当参数为4个时,等同于'q',绘制二次贝塞尔曲线。
当参数为6个时,等同于'c',绘制三次贝塞尔曲线。
有些精通SVG的同学这时候可能就要问我了,不对啊,二次贝塞尔曲线和光滑三次贝塞尔曲线的参数都是4个,你这里没有光滑三次啊?因为开发的同学留坑没写了呀(微笑)。
Transform,ClippingRectangle,Pattern,RadialGradient,LinearGradient 未完待续...
在react-art的库中,有个神奇的lib文件夹,下面除了ReactART.js以外,还有Circle.art.js,Rectangle.art.js,Wedge.art.js等,其中Circle和Rectangle分别对应于svg规范中的圆形/<circle/>,矩形/<rect/>,而Wedge则是用于生成扇形。当然,这些module都很不完善,很有可能需要二次开发,如果这样,推荐拷贝库文件到工程中再行修改。
引入它们的语句为 var Circle = require('react-art/lib/Circle.art');
。这种不同寻常地引用方式是Facebook开发和维护的 fbjs 引入的,react-native依赖了fbjs,而所有需要被输出的js文件的头部都会以 // @providesModule Circle.art
的形式标明。
使用示例:
<Circle radius={10} stroke="green" strokeWidth={3} fill="blue" />
值得一提的是,Circle.art.js是个半成品,可以看到它根本没有实现svg规范中的cx和cy,因此画出来的圆的圆心始终在左上角,显示出来的也就只有半个圆。请在实际应用中自行实现,或者使用笔者提供的 修改版本 。
使用示例:
<Rectangle width={200} height={400} stroke="red" strokeWidth={10} fill="FFFFFF" />
使用上述代码,就很直观看到这个module的缺陷了,矩形四条边不等宽(扶额)。
此外还接受的props有:
radius
radiusTopLeft
radiusTopRight
radiusBottomLeft
radiusBottomRight
这里的radius指的是圆角矩形的圆角半径,接受的值类型为数字,radius为四个角的通用半径,但如果设置了具体某个角的半径,则用后者。
Wedge是楔子的意思,然而在这里却是生成各种角度的扇形=_=。使用示例:
<Wedge outerRadius={50} stroke="red" startAngle={0} endAngle={100} fill="FFFFFF" />
生成的图形如下图:
可选Props为innerRadius,用于生成一个圆环扇形,如下图。
呐,一看这个module也是半成品,如果stroke有颜色而fill为白色就露馅了,曲线没闭合。因此,如有需求,请自行弥补。