この記事はACCESS Advent Calendar 1日目の記事です。
こんにちは ACCESS開発本部IoT開発部の渡辺 (@sassy_watson) です。
今回は私がSVGをcanvasで使う方法についての記事を書こうと思います。
SVGとCanvas
SVGはただのベクターグラフィックスというだけでなく、
マスクやクリップだったらグラデーションやフィルターだったり
いろいろ高機能なのが魅力です。
ただ、XMLなのでJavaScriptでなにかしようするときのDOM操作が面倒くさいです。
一方、CanvasはAPIが簡単なのでJavaScriptで扱いやすいというメリットがあります。
SVGをCanvasで使う
そこで、SVGで使いたい機能をSVGで書いて、canvasに貼り付けるというアプローチが考えられます。
素材はillustratorでつくって、Canvasでペタペタ貼り付けるようなことをしたかったりします。
SVGはimg要素で画像として扱うことができます。
ということは、imgでSVGを指定して、それをcanvasのdrawImageで使えばSVGをcanvasで扱うことができます。
<canvas id="c" width="200" height="200"></canvas>
var img = new Image();
img.src = 'http://www.w3.org/Icons/SVG/svg-logo-v.svg';
img.onload = function() {
var c = document.getElementById('c');
var ctx = c.getContext('2d');
ctx.drawImage(img, 0, 0, 200, 200);
}
とすれば、ちゃんと
と表示されます。
(下記で確かめられます。)
http://jsfiddle.net/sassy_watson/o87sux0o/
これは、SafariでもChromeでもEdgeでも動きます。
Firefoxが…・
ただ、これはFirefoxでは動かないのです。
FirefoxはcanvasでSVGを指定したimgを描画できません。
srcにbase64エンコーディングしたSVGを描画できるという情報もありましたが、試してみたらできませんでした。(ちなみにバージョンは42)
これは困った。
そこでcanvgですよ
canvgはSVGをパースして、その内容をもとにcanvasに描画していくライブラリです。
こちらならFirefoxでも描画できそうです。
svg = '<svg><rect x="50" y="50" width="100" height="100" /></svg>';
canvg(document.getElementById('canvas'), svg);
とすれば簡単にSVGが描画できます。
canvgには上記のようなSVGの文字列の他にファイル名も指定できます。
ただ、
canvg(document.getElementById('canvas'), 'http://www.w3.org/Icons/SVG/svg-logo-v.svg');
みたいにすると、canvgが中でXMLHttpRequestを使ってSVGファイルを取得しようとするのでSOPでうまくいかないこともあるので注意です。
canvgの制限
canvgがどこまでサポートしているかはわかりませんが、
たぶんcanvasがサポートしている範囲でしかできません。
canvasがサポートしていないfilterの機能とかは利用できないようです。
例えば、feGaussianBlurとかは、blurをサポートしているブラウザでは動きます。
svg = '<svg xmlns="http://www.w3.org/2000/svg">'
+'<defs>'
+' <filter id="gaussian" x="0" y="0" width="100" heihgt="100" filterUnits="objectBoundingBox">'
+' <feGaussianBlur in="SourceGraphic" stdDeviation="5,10" />'
+' </filter>'
+' </defs>'
+' <circle cx="50" cy="50" r="50" fill="red" stroke="blue" stroke-wdith="5" filter="url(#gaussian)" />'
+'</svg>';
canvg(document.getElementById('canvas'), svg);
しかし、feComponentTransfer等はうまくいきませんでした。
http://jsfiddle.net/sassy_watson/ymwd6n49/3/
これはせっかく高機能なSVGの機能を制限してしまうことになるので少々残念です。
まとめ
ということで今回はSVGをcanvasに描画する方法としてcanvgを紹介しました。
他に良い方法はないかどうかは調査していこうと思います。
明日は @magicant さんです。
明日もよろしくお願いいたします。