初窺基于 react-art 庫的 React Native SVG

wapjingle 8年前發布 | 32K 次閱讀 SVG JavaScript開發 React Native

來自: 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>

 本文由用戶 wapjingle 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!