初窥基于 react-art 库的 React Native SVG
技术背景在移动应用的开发过程中,绘制基本的二维图形或动画是必不可少的。然而,考虑到Android和iOS均有一套各自的API方案,因此采用一种更普遍接受的技术方案,更有利于代码的双平台兼容。 art是一个旨在多浏览器兼容的Node style CommonJS模块。在它的基础上,Facebook又开发了react-art ,封装art,使之可以被react.js所使用,即实现了前端的svg库。然而,考虑到react.js的JSX语法,已经支持将 然而,在移动端,考虑到跨平台的需求,加之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端和移动端上了。 成功运行Vector-Widget后的效果图: Vector-Widget额外实现了旋转,以及鼠标点击事件的旋转加速响应。Web端可以看到点击加速,但是在移动端无效,原因是React Native并未对Group中onMouseDown和onMouseUp属性作处理。本文着重于静态svg的实现,暂时无视动画部分效果即可。 此外还可以用该例子感受一下叹为观止svg动画的性能占用(摊手)。 原理和调用获取ARTpackage.json中需要引入art库,笔者的版本设置是 Android与iOSvar React = require('react-native'); var ReactART = React.ART; 或者使用ES6的Destructuring特性: var { ...,ART,...,} = React; Web端var React = require('react'); var ReactART = React.ART; 基本组件获取方式接下来的所述的代码,web端和移动端都是通用的,这也是React Native的诱惑所在。 var { Shape,Group,Transform,Surface,} = React.ART; Surface所有的svg component必须被一个Surface标签所包含。
GroupGroup用于组合art component。比如在一个函数中返回多个svg component的情况,此时就必须要用 style:margin和padding系列均无效,我怀疑不接受style。 function _render() { return ( <Group> <Shape d={"M160 160 A 45 45,1,115 205"} stroke="#000000" strokeWidth={3} /> <Shape d={"M160 160 A 45 45,115 205"} stroke="#000000" strokeWidth={3} /> </Group> ); } ShapeShape用于生成路径,语法与svg中的<path>很相似。Shape的Props如下:
Path语法更近似于移动端。使用方法: 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... :
Transform实现代码路径:art/core/transform.js Transform对象中的函数:
<Surface width={700} height={700}> <Rectangle width={100} height={200} stroke="red" strokeWidth={10} fill="FFFFFF" transform={new Transform().translate(150,150).scale(2)} /> <Rectangle width={100} height={200} stroke="yellow" strokeWidth={10} fill="FFFFFF" transform={new Transform().translate(150,150).scaleTo(1,2)} /> <Rectangle width={100} height={200} stroke="blue" strokeWidth={10} fill="FFFFFF" transform={new Transform().translate(150,150)} /> </Surface>
<Surface width={700} height={700}> <Rectangle width={100} height={200} stroke="red" strokeWidth={10} fill="FFFFFF" transform={new Transform().translate(150,150)} /> <Rectangle width={100} height={200} stroke="red" strokeWidth={10} fill="FFFFFF" transform={new Transform().translate(150,150).rotate(30,100,100)} /> </Surface> <Surface width={700} height={700}> <Rectangle width={100} height={200} stroke="red" strokeWidth={10} fill="FFFFFF" transform={new Transform().translate(150,150)} /> <Rectangle width={100} height={200} stroke="red" strokeWidth={10} fill="FFFFFF" // 差别在这里 transform={new Transform().translate(150,150).rotate(30)} /> </Surface> 效果如下图所示: react-art中的lib引入lib中的module在react-art的库中,有个神奇的lib文件夹,下面除了ReactART.js以外,还有Circle.art.js,Rectangle.art.js,Wedge.art.js等,其中Circle和Rectangle分别对应于svg规范中的圆形 引入它们的语句为 Circle使用示例: <Circle radius={10} stroke="green" strokeWidth={3} fill="blue" /> 值得一提的是,Circle.art.js是个半成品,可以看到它根本没有实现svg规范中的cx和cy,因此画出来的圆的圆心始终在左上角,显示出来的也就只有半个圆。请在实际应用中自行实现,或者使用笔者提供的修改版本。 当然,不用cx和cy的话,也可以设置tranform来实现平移。如: <Circle radius={10} stroke="green" strokeWidth={3} fill="blue" transform={new Transform().translate(100,100)} /> 两种方法都可以达到平移效果,但是cx,cy的方式相对来说更简洁,可读性也更好。 Rectangle使用示例: <Rectangle width={200} height={400} stroke="red" strokeWidth={10} fill="FFFFFF" /> 使用上述代码,就很直观看到这个module的缺陷了,矩形四条边不等宽(扶额)。
这里的radius指的是圆角矩形的圆角半径,接受的值类型为数字,radius为四个角的通用半径,但如果设置了具体某个角的半径,则用后者。 WedgeWedge是楔子的意思,然而在这里却是生成各种角度的扇形=_=。 <Wedge outerRadius={50} stroke="red" startAngle={0} endAngle={100} fill="FFFFFF" /> 生成的图形如下图: 技术缺陷除了之前所提到的各种各样的实现上的不完善以外,svg规范在React Native上应用的最大问题在于,有一大批web上的svg支持的css属性,还没有在React Native上实现。 以stroke类的一大批属性为例,目前可用的只有线条颜色stroke和strokeWidth,而如stroke-dasharray,stroke-dashoffset这样的可以用之实现神奇的描边等效果的CSS属性,目前还没有被支持。 在性能占用方面,静态svg尚可接受,但如果是svg annimation,实测红米Note 2上的CPU占用率即可达50%左右,故其在生产环境的大规模应用,恐怕还需进一步的性能优化。 ==================================== (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |