初窺基于 react-art 庫的 React Native SVG
來自: https://segmentfault.com/a/1190000004422456
技術背景
在移動應用的開發過程中,繪制基本的二維圖形或動畫是必不可少的。然而,考慮到Android和iOS均有一套各自的API方案,因此采用一種更普遍接受的技術方案,更有利于代碼的雙平臺兼容。
art 是一個旨在多瀏覽器兼容的Node style CommonJS模塊。在它的基礎上,非死book又開發了 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端和移動端上了。
原理和調用
獲取ART
package.json中需要引入art庫,筆者的版本設置是 art: ^0.10.0 。
Android與iOS
var 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標簽所包含。Props如下:
-
width: Surface的寬度。
-
height: Surface的高度。
-
style: margin系列和padding系列都生效。
Group
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
Shape用于生成路徑,語法與svg中的<path>很相似。Shape的Props如下:
-
d: 語法與svg規范相同
-
stroke: 線條顏色,"#FFFFFF"的形式
-
strokeWidth: 線條寬度,{3}的形式
-
transform:接受 new ART.Transform()生成的object,具體見下文Transform條目。
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} />
}</pre>
可以看到,取出的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
引入lib中的module
在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'); 。這種不同尋常地引用方式是非死book開發和維護的 fbjs 引入的,react-native依賴了fbjs,而所有需要被輸出的js文件的頭部都會以 // @providesModule Circle.art
的形式標明。
Circle
使用示例:
<Circle radius={10} stroke="green" strokeWidth={3} fill="blue" />
值得一提的是,Circle.art.js是個半成品,可以看到它根本沒有實現svg規范中的cx和cy,因此畫出來的圓的圓心始終在左上角,顯示出來的也就只有半個圓。請在實際應用中自行實現,或者使用筆者提供的 修改版本 。
Rectangle
使用示例:
<Rectangle width={200} height={400} stroke="red" strokeWidth={10} fill="FFFFFF" />
使用上述代碼,就很直觀看到這個module的缺陷了,矩形四條邊不等寬(扶額)。
此外還接受的props有:
</div>
-
radius
-
radiusTopLeft
-
radiusTopRight
-
radiusBottomLeft
-
radiusBottomRight
這里的radius指的是圓角矩形的圓角半徑,接受的值類型為數字,radius為四個角的通用半徑,但如果設置了具體某個角的半徑,則用后者。
Wedge
Wedge是楔子的意思,然而在這里卻是生成各種角度的扇形=_=。使用示例:
<Wedge outerRadius={50} stroke="red" startAngle={0} endAngle={100} fill="FFFFFF" />
生成的圖形如下圖:
可選Props為innerRadius,用于生成一個圓環扇形,如下圖。
吶,一看這個module也是半成品,如果stroke有顏色而fill為白色就露餡了,曲線沒閉合。因此,如有需求,請自行彌補。
</div> </div>