LoginSignup
34
35

SVGをcanvasで使う

Last updated at Posted at 2015-11-30

この記事は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);
}

とすれば、ちゃんと

スクリーンショット 2015-11-28 10.19.25.png

と表示されます。
(下記で確かめられます。)
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 さんです。
明日もよろしくお願いいたします。

34
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
35