HTML5中有兩種圖形解決方案:SVG和Canvas,二者都有各自特色,這裏很少說,Qunee圖形組件中咱們經常使用SVG做爲節點圖標,這在大部分場景下都表現良好,可是IE下有些小問題,IE下能夠將SVG圖片繪製到Canvas上,可是沒法讀取SVG的像素信息,這意味着一些特殊功能(追蹤圖片邊緣,圖片染色等)沒法被實現,這時候咱們考慮選擇將SVG解析,轉換成Canvas的繪製代碼,這樣就能夠使用Canvas來繪製SVG圖片了 javascript
是的確實有人在作這樣的事,canvg.js 就是一個將SVG轉換成Canvas的工具庫,甚至有些SVG的動畫效果也能獲得實現,可是canvg.js存在不少問題: html
SVG是一種很複雜的矢量圖形語言,徹底轉換到Canvas至關於寫一個獨立的SVG查看器,即便是Adobe的SVG Viewer也會存在兼容問題,更況且一個小小的js工具庫 java
canvg.js確實能將SVG繪製到Canvas上,可是沒法生成繪製代碼,就意味着須要引入這個類庫,且動態解析SVG,這裏存在額外的性能開銷,加上canvg.js自己並不完善,代碼封裝性仍是功能上都存在缺陷,在生產環境中引入會帶來問題 node
網上搜索svg to canvas,能夠找到這個:http://www.professorcloud.com/svg-to-canvas/ 能夠將SVG轉換成Canvas,並輸出javascript代碼,符合製做矢量圖標的須要,Qunee早期的內置icon都是這樣製做的,可是這個工具並不完善,不支持漸變,不支持紋理,大部分的SVG圖標沒法轉換,因而咱們考慮本身寫一個在線工具,以方便客戶使用,咱們查看了http://www.professorcloud.com/svg-to-canvas/ 的代碼,它是在某個老版本的canvg.js基礎上修改實現的,是寫死的代碼,不方便後期升級和維護,咱們想到一種更好的方式來實現 git
咱們想到一種更好的方式實現SVG到Canvas代碼的轉換,在線地址:http://demo.qunee.com/svg2canvas/ github
經過重寫HTMLCanvasElement相關的方法來實現,基本的思路就是將CanvasRenderingContext2D.prototype中的相關繪製和設置代碼重寫,增長上生產js代碼的功能,好比對CanvasRenderingContext2D#fill()方法的處理,咱們可能要重寫這個方法 正則表達式
CanvasRenderingContext2D.prototype.fill2 = function(){ this.fill(); appendCode('ctx.fill();\n');//生成js代碼 }
固然實際上要比這複雜,須要考慮如何重寫方法?如何將參數對象轉換成字符串?此外對於複雜的SVG,可能會須要建立臨時的Canvas對象,還涉及到一些正則表達式,還要注意做用域的問題,花費了些功夫,實現了一套不錯的工具,基本上canvg.js能支持的svg,都能很好的轉換,支持Gradient, 支持Pattern等 canvas
好的東西若是隻是本身使用,未免太浪費了,因而咱們又花了很多時間將其作出了一個好的界面,並公佈出來 瀏覽器
在線地址:http://demo.qunee.com/svg2canvas/ app
支持Chrome, Safari瀏覽器,左中右佈局分佈,將svg文件拖拽到左側虛線框中,便可生成Qunee for HTML5中相應的圖片註冊代碼,並及時預覽到圖片在Qunee for HTML5中的展現效果,以下:
將右側文本框中的代碼保存到js文件(好比SVGIcons.js),並在HTML中引入這個js,以後你就能夠直接使用svg文件名做爲節點圖標了
node.image = 'DataCenter.svg';
示例代碼
<!DOCTYPE html> <html> <head> <title>Hello Qunee for HTML5</title> <meta charset="utf-8"> </head> <body style="margin: 0px"> <div style="position: absolute; width: 100%; top: 0px; bottom: 0px;" id="canvas"></div> <script src="http://demo.qunee.com/lib/qunee-min.js"></script> <script src="SVGIcons.js"></script> <script> var graph = new Q.Graph('canvas'); var node = graph.createNode("SVG"); node.image = 'DataCenter.svg'; </script> </body> </html>
運行效果