SVGのpathをcanvasに描画できるPath2D API

SVG の path を canvas にそのまま描画できる Path2D API を使ってみます。

Path2d API

基本的な使い方は下記リンクを参考にしてください。

参考:Path2D()|MDN

new で作ってあげた Path2D に SVG の d 値を入れれば描画できます。

Path2D API

以下の SVG を canvas に写してみます。

SVG

<svg id="test-svg" viewBox="0 0 300 300" width="300" height="300">
    <path d="M162 266.3l-.9 6.5s19 9 26.3 6.4c7.3-2.7 6.3-5.4 6.5-8.3.3-3-26.5-3-31.8-4.6zM132.4 276.6l-1 6.5s19 9 26.3 6.4c7.3-2.7 6.3-5.4 6.6-8.3.2-3-26.5-3-31.9-4.6z" fill="#e6cd8e"/>
    <path d="M149.6 270.5s-1.5 4.4-5.6 7c-4.2 2.4-9.6-2.1-9.6-2.1l1.1-31.6 14.6-.1-.5 26.8z" fill="#ede7dd"/>
    <path d="M135.3 250.8l.8.4 2.4.8a19.7 19.7 0 0 0 10.2-.3l1.2-.4v3.5h-.3a24.6 24.6 0 0 1-12 .3l-2.4-.8v-3.5zM135 257.9l.4.1c.8.4 1.6.6 2.4.8a20.2 20.2 0 0 0 12-.8v3.4l-.7.2a24.7 24.7 0 0 1-12.2.3l-2-.6.1-3.4zM134.8 264.7l.2.1a21.3 21.3 0 0 0 13.2.5l1.5-.4v3.4l-.6.2a25.8 25.8 0 0 1-12.3.3l-2.1-.7v-3.4z" fill="#2d2b38"/>
    <path d="M164.2 263.1l1-23.3 14.5-2.2-.4 23.6s-1.5 3.9-5.6 6c-4.2 2.3-9.5-4-9.5-4z" fill="#ede7dd"/>
    <path d="M163 261l-1.3 8.2s17 10.7 25.3 8.3c8.3-2.4 10-12.2 5.4-13.4-4.6-1.2-8.3-1.5-8.3-1.5s-2.9-3.1-7.3-1c-4.4 2.3-2.9 4.2-2.9 4.2s-6.3 4.4-11-4.9zM133.3 271.2l-1.2 8.2s17 10.7 25.3 8.3c8.2-2.4 10-12.2 5.3-13.4-4.6-1.2-8.3-1.4-8.3-1.4s-2.9-3.2-7.3-1c-4.3 2.2-2.9 4.1-2.9 4.1s-6.3 4.4-11-4.8zM165 241.6h.2a23.8 23.8 0 0 0 14 .5h.4v3.3l-2.8.6a27 27 0 0 1-9.5-.4l-2.4-.6.2-3.4zM164.8 249l.5.3 2.4.7a20 20 0 0 0 11.6-.7l.2.6v2.8l-.6.1a24.5 24.5 0 0 1-12.1.3l-2.2-.7.2-3.4z" fill="#2d2b38"/>
    <path d="M164.5 256.3l1.2.5 2.6.8a21.6 21.6 0 0 0 10.6-.3l.4-.1v3.3l-2.8.6a24.8 24.8 0 0 1-12-1.3h-.2l.2-3.5z" fill="#2d2b38"/>
    <path d="M110.9 173.7c16.7-.1 121.7-1 131.3-35.8 9.7-35-179.7-95.7-170.5-114 0 0-8.8 14.5-.5 53.7 0 0-33.2 96.5 39.7 96z" fill="#363634"/>
    <path d="M88.2 128.3s-34-19.2 3.5-72c0 0-24 13.5-20.5-31.9 0 0 34-4 42.7 2.6 0 0 48-23.1 74.2-6.5 0 0 36.3-16.6 42.4-9.6 6 7 5.6 39.2 0 48 0 0 39 69.7 4.8 99-18.8 16.2-33.6 12.7-54.2 11.4-20.5-1.3-71-30.6-93-41z" fill="#565654"/>
    <path d="M89 138.7s8.8 33.2 72 31c63.4-2.1 65.1-29.6 74.3-49.7 9.1-20.1-41-65-65-59-24 6.2-75.6 32.8-81.2 77.7z" fill="#ffddba"/>
    <path d="M157 114.9l1.2.1a8.2 8.2 0 0 1 5.2 4.2 11 11 0 0 1 1 2.5l3.4-.3a274.6 274.6 0 0 1 10.4-.5v-.5c0-1.3.5-2.6 1-3.7a16.5 16.5 0 0 1 5.8-6.5 7 7 0 0 1 3-1l24-3h.2c.7 0 1.4.2 2.1.5.9.3 1.7.8 2.5 1.3a32.4 32.4 0 0 1 4.4 3.3 37.3 37.3 0 0 1 5.9 6.9c.3.7.6 1.4.6 2.2v.2l-.9 8.6v.3c0 .9-.2 1.7-.6 2.5a16.3 16.3 0 0 1-4.3 6c-.6.5-1.3 1-2 1.3a6.4 6.4 0 0 1-2.4.6l-28.9 3h-1l-1.7-.7c-.7-.3-1.3-.8-2-1.3a15.2 15.2 0 0 1-3.7-4.8c-.6-1.2-1-2.5-1.1-3.9l-.6-8-13.7.8c0 3.7-.2 7.5-.4 11.3v.5a10.7 10.7 0 0 1-.6 3c-.8 2-2.2 3.8-4.2 4.8a6.6 6.6 0 0 1-2.7.6l-31 3.9h-.3a5 5 0 0 1-.8 0c-1.3-.3-2.5-1-3.4-2a10.6 10.6 0 0 1-1.7-2 18.1 18.1 0 0 1-2.4-4.8c-.4-1-.6-2-.6-3V124a10.8 10.8 0 0 1 1.4-5 8.2 8.2 0 0 1 4.7-4l1.4-.1c11-.1 21.9-.3 32.8 0zm-32.7 3.2a3 3 0 0 0-.6 0 4 4 0 0 0-2.3 1.7 7 7 0 0 0-1 1.8 8 8 0 0 0-.5 2.5v13.1l.3 1.5a12.4 12.4 0 0 0 1.6 3.7l1.2 1.8c.5.5 1 1 1.5 1.3.3.2.7.3 1 .3l31.1-3.9h.8l.5-.2c1-.3 1.8-1.1 2.3-2a6.4 6.4 0 0 0 .8-2l.2-1v-.5l.4-12a6 6 0 0 0-.6-2.6 8 8 0 0 0-1.2-2 4.5 4.5 0 0 0-2.4-1.4h-.5c-10.9-.2-21.7 0-32.6 0zm64-5.7h-.3-.2l-.8.4-.9.5-1.4 1.3a15 15 0 0 0-3 4.7 4 4 0 0 0-.2 1l.8 11.8v.2a4.5 4.5 0 0 0 .5 1.6 10.4 10.4 0 0 0 1.8 3c.4.6.9 1 1.4 1.5l1.5 1 1 .3c9.6-.6 19.2-2.4 28.8-3h.2c.4 0 .8-.2 1.1-.4l1.5-1a12.3 12.3 0 0 0 3.3-5l.2-1.2v-.1l.9-8.6v-.2l-.3-.6-.4-.6-1.3-1.7a33.5 33.5 0 0 0-10.3-8l-23.9 3.1z" fill="#514847" />
    <path d="M90.4 130s22.7 28.8 31 30.1c0 0-10-25.3-6.2-32.3 0 0 3.5 10.5 7 10.5 0 0-2.2-33.6 2.2-36.2 0 0 6.6 14 5.7 21.8 0 0 15.7-23.1 14.4-31 0 0 10.9 23.2 8.7 24.9 0 0 4.8-11 15.3-26.2 0 0 8.7 22.3 5.2 27.5 0 0 21.8-12.2 23.6-38.8 0 0-1.8 20.5-3 23 0 0 7.4-5.1 8.7-15.2 0 0 4.8 21 1.3 22.7 0 0 5.6-.9 10.5-10.9 0 0 4.3 22.3 2.1 25.8 0 0 2.9-.7 5.7-2.2 0 0 1.3 16.1-3 21.4 0 0 12.6-5.7 18.7-31s-42.8-89-67.2-79c-24.4 10-76.8 44-80.7 95.1" fill="#995e46"/>
    <path d="M136.2 172s-38.9 8.2-54.1-11.4c-15.3-19.7 3-43.7 7-56.8 3.9-13 32.3-67.6 68-74.2 35.8-6.5 67.3 11.8 81.7 55.5 14.4 43.6 23.5 63.4-28.8 77.2-36.4 9.6-30.6 6.2-30.6 6.2s53.7-12.7 56.7-26.7-10.4-81.2-46.7-95.1c-36.2-14-77.6 35.3-82 58.9-4.4 23.5-28.8 62.8 2.6 60.6 31.4-2.1 34.5 6.2 26.2 5.7z" fill="#489dc2"/>
    <path d="M123.8 205.2l-6 25.4 7.9 1.7 12.8-25.9-14.7-1.2z" fill="#2a2020"/>
    <path d="M116 202s-5.5-13.7-.2-13.7c2.5 0-1.4 8.9 2.8 11.2 4 2.2-2.6 2.6-2.6 2.6zM114.3 206s-15.1-5.7-16.8 6c-1 6.8 4.6 3 11.7 4.7 7 1.7 4.4-8 5-10.8z" fill="#494040"/>
    <path d="M145.8 125.2c2.3 0 3.6 3.8 3.6 8.5s-1.3 8.5-3.6 8.5-4.2-3.8-4.2-8.5 1.9-8.5 4.2-8.5zM192.4 120.8c2.3 0 4.4 3.7 4.4 8.4s-2 8.6-4.4 8.6c-2.3 0-4.2-3.8-4.2-8.5s2-8.5 4.2-8.5z" fill="#1c2680"/>
    <path d="M190.3 150.3h.2l.6.3a1.6 1.6 0 0 1 0 2.6v.1l-.6.3a30 30 0 0 1-6.9 3c-1.5.3-3 .5-4.5.4a14 14 0 0 1-6.4-1.8 45.1 45.1 0 0 1-7.7 3.6 25 25 0 0 1-5 1.1h-3.7a13.3 13.3 0 0 1-5.9-2.3l-1.2-1v-.1l-.2-.3a1.6 1.6 0 0 1-.1-1.2 1.6 1.6 0 0 1 1.5-1.2c.4 0 .7.1 1 .3l.4.4.2.2a9.2 9.2 0 0 0 6.1 2 14.6 14.6 0 0 0 4.1-.5 22.2 22.2 0 0 0 4-1.3 34.5 34.5 0 0 0 5.6-3l2 .1.1.2.3.1a9.2 9.2 0 0 0 3.4 1.3l1.5.2a15.8 15.8 0 0 0 8.8-2.4l1.4-.8.1-.1.3-.1h.6z" fill="#e9b586" />
    <path d="M130 179.8s-19.1 29.7-20 31.8c-2.7 6.5-16.1.9-6.1 16.6 10 15.7 19.2.5 18.8-7.4-.5-7.9 10.1-31.3 13.5-35.8.1-.1-6.1-5.2-6.1-5.2zM180.3 183.5s24.4-10 38.8-15.4c4.9-1.9 6.2.3 10-2.7 4-3.1 1.2-12.8-7.7-9.7-2.8 1-3 4.7-6.3 6-15.3 5.9-35.5 10.4-35.5 10.4l.7 11.4z" fill="#ffddba"/>
    <path d="M206.7 172.9l5.8-2.3-2.5-7.1-5.8 2 2.5 7.4z" fill="#404040"/>
    <path d="M183.6 225.2l1.7 12.1s-11.2 7-24.8 5.9l.5-5.4s20.7-5.6 22.6-12.6zM137.3 236l-4.8 8.6s23 4.4 25.6-.2c2.7-4.6-.3-6.3-.3-6.3l-20.5-2.1z" fill="#383837"/>
    <path d="M178.5 187l6.1 39c-6.5 19.7-39.2 6.1-39.2 6.1v-48l-10 3.5-7-8.3 11.7-7.8 35.4-1.8 7.3 1.4 1 11.5-5.3 4.4z" fill="#545353"/>
    <path d="M150.2 173a11 11 0 0 1 4.3 1l1.3.7a18.9 18.9 0 0 1 7.2 7.5 31.5 31.5 0 0 1 2.3 4.7 38 38 0 0 1 .3-2.1 17.2 17.2 0 0 1 3.4-7.8 11.9 11.9 0 0 1 4.7-3.3l.2-.1.4-.1a.8.8 0 0 1 .5 1.5h-.1l-.4.2a11.6 11.6 0 0 0-2.4 1.3 10 10 0 0 0-1.8 1.7 14.3 14.3 0 0 0-3 7.2 25.7 25.7 0 0 0-.4 5.5v.2l.3 1 .2.8a68.8 68.8 0 0 1 2.2 14.3l-1.6.3a49.1 49.1 0 0 1-1.5-6.1 57.1 57.1 0 0 1-1.5-10.8 44.2 44.2 0 0 0-4.4-9.5 15.9 15.9 0 0 0-6.5-5.6 10.5 10.5 0 0 0-4.4-.8h-.2l-.4-.2a.8.8 0 0 1 .2-1.4h1.1z" fill="#489dc2" />
    <path d="M182 208.8l1.5 9.7a2 2 0 0 1-1.3.5c-2 0-3.4-2.4-3.4-5.3 0-2.8 1.3-4.9 3.1-5zM176.8 208.4c1.1 0 2 .9 2.2 2.1 0 1.2-.9 2.3-2 2.3-1.2 0-2.2-.5-2.2-1.7 0-1.3.8-2.6 2-2.7zM179 201.8c1 0 1.8 1.2 1.8 2.7 0 1.5-.8 2.7-1.8 2.7s-2.3-.7-2.3-2.2c0-1.5 1.3-3.2 2.3-3.2z" fill="#489dc2"/>
    <path d="M153.7 169.7l11.3 14 1.3-15.3-12.6 1.3z" fill="#ffddba"/>
    <path d="M128.6 233s-2.4 13.6 2.5 14.3c4.8.7 7.4-10.6 7.4-10.6l-9.9-3.7z" fill="#2a2020"/>
    <path d="M124 223.6l-3.5 7.8 7.4 3.6 5.5 8.6 4.8-5.4-7-5.4-7.1-9.2z" fill="#cd3541"/>
    <path d="M133.2 200.5s2.8-17 8.6-16.4c4 .4 8.5 7.2 10.3 11.7 10.2 1.3 16.1 8.4 17.3 18.8.1-.6 0 0 0 0 5.2 2.4 13.8 6.6 13 9.8-.8 3-12.3 8.8-14.7 7.6-2.2 6.3-7 10-15.6 10-13.4 0-27.8-11-27.8-24.4 0-7.3 3.5-13.2 8.9-17z" fill="#494040"/>
    <path d="M142 227.4h2.8l.6 3.2-3.4.2v-3.4z" fill="#f0aaa7"/>
    <path d="M128.9 215.6a.8.8 0 0 1 .6.4 126.8 126.8 0 0 1 3.6 6 .8.8 0 0 1-.2.5c-.2.3-.6.4-1 .3a127.5 127.5 0 0 1-3.9-6.2.8.8 0 0 1 .9-1zM126.5 218.8a133.8 133.8 0 0 1 5.5 4.7.8.8 0 0 1-.6 1.1.8.8 0 0 1-.7-.2 134.7 134.7 0 0 1-5-4.5.8.8 0 0 1 .7-1.1zM149.3 236.4h.3a119 119 0 0 1 5.1 3.6.8.8 0 0 1-.5 1.2.8.8 0 0 1-.6-.1 120.9 120.9 0 0 1-5.1-3.6v-.2a.8.8 0 0 1 .7-1zM147.4 238l.5.1a127.5 127.5 0 0 1 4.9 4.2.8.8 0 0 1 0 .6.8.8 0 0 1-1.3.3 131.4 131.4 0 0 1-4.8-4.1.8.8 0 0 1 .6-1.1h.1z" fill="#7e7373" />
    <path d="M168.6 223.6l12.2.8s-9.8 5.6-11.4 6c-1.6.4-.8-6.8-.8-6.8zM136.4 200l12.6-.8s-5-13.1-7.8-13.1-7 13.5-4.8 14z" fill="#f0aaa7"/>
    <path d="M136.1 213c1.9 0 3.3 2.4 3.3 4.3 0 2-1.4 2.7-3.3 2.7-1.8 0-3.3-1.6-3.3-3.5 0-2 1.5-3.5 3.3-3.5zM155.3 229.6c1.8 0 3.3 1.6 3.3 3.5 0 2-1.5 3.5-3.3 3.5-1.8 0-3.4-2.2-3.4-4.1 0-2 1.6-3 3.4-3z" fill="#d3a528"/>
    <path d="M66.4 244.9h.2l.4.2a1.6 1.6 0 0 1 .7 2l-.1.3-16.3 25.2 14.8-4.9h.4a1.6 1.6 0 0 1 .8 3l-.2.1-19.1 6.3h-.3a1.6 1.6 0 0 1-1-.1 1.6 1.6 0 0 1-.7-2.1l.1-.2L62.6 249l-20.2 5H42a1.7 1.7 0 0 1-1-.3 1.6 1.6 0 0 1-.4-2.2c.2-.3.4-.5.7-.6h.3l24.2-6H66.4zM95 239.4h.2l.4.1a1.6 1.6 0 0 1 .8 2v.2l-12.1 25.4 15.6-4.5h.4c.3 0 .7 0 1 .2a1.6 1.6 0 0 1 .5 2 1.7 1.7 0 0 1-.7.8l-.3.1-19 5.5h-.3a1.6 1.6 0 0 1-1.8-2l.1-.2 12.3-26-15 1.8h-.2-.2l-.6-.1a1.6 1.6 0 0 1-.7-2c0-.3.1-.4.2-.5.2-.3.5-.5.8-.5l.3-.1 18-2.2h.2z" fill="#489dc2" />
</svg>

SVG 画像です。

制限事項

今回作るコードの簡略化のため SVG 要素に以下の制限を加えます。

SVG の子要素は g 要素、他の形状の要素なども含めず path のみ。孫要素もなし。

実際に canvas に描画するサイズで SVG を作成する 。今回は 300px ✕ 300px。

JavaScript を使ってコードを書くので色々柔軟に対応可能ですが、際限がないので今回は上の状態にします。

Illustrator などのペンツールを使って書いたパスを SVG として出力すれば path 要素として書き出されます。

svgPathToCanvas

自動で canvas に描画できるような関数を作ってみます。

JavaScript

function svgPathToCanvas(canvasId, svgId) {
    var canvas = document.getElementById(canvasId); // canvas 要素の取得
    var ctx = canvas.getContext("2d");
    var svg = document.getElementById(svgId); // SVG 要素の取得
    var svgChildren = svg.children; // 子要素 path 要素の取得

    // 子要素を for で総当り
    for (var i = 0; i < svgChildren.length; i++) {
        var p = new Path2D(svgChildren[i].getAttribute("d")); // path の d 値を取得
        ctx.fillStyle = svgChildren[i].getAttribute("fill"); // path の fill 値を取得
        ctx.fill(p);
    }
}

//使用例 canvas 要素と SVG 要素の id を指定
svgPathToCanvas("canvas", "test-svg");

描画につかう canvas と SVG にそれぞれ id をつけて、それを引数にいれるだけで canvas に描画する script です。

仕組みは簡単で、子要素である path の d 値と fill 値を引っ張って Path2d API で使います。

サンプル

上の SVG 画像を canvas に描画したものです。

canvas に描画したものでピクセルドットでの描画に変換されるようですが SVG と基本的に変わらずに描画できています。

対応ブラウザ

調べられる範囲で調べたブラウザの対応状況です。

ブラウザ対応状況
GoogleChrome
Firefox
Safari
InternetExplorer
MicrosoftEdge

案の定 IE は未対応、Edge も未対応な状況なのでバリバリ使うというのは難しそうです。

以前記事で書いた「わぷーの塗り絵をcanvasとSVGで作ってみる」では IE が SVG を描画した canvas の PNG 書き出しに対応いていなかったのですが、この場合 Psth2D API 自体に対応していないので、これを使っても IE は SVG の PNG 変換ができません。悲しいです。

まとめ

SVG を canvas に描画する意味があるのかないのかという問題はありますが、このような簡単な変換で描けてしまうのは楽しいです。

path 以外の形状の要素も Path2D API を上手く使えば canvas への描画は可能で、上手く作れば万能な形での script も作れそうです。すでに万能なライブラリもあるようなので気になる方はチェックしてみてください。