SVGにCanvasを描画するサンプル

icon 項目のみ表示/展開表示の切り替え

概要

SVGにCanvasを描画するサンプルです。
下図は、外と青い四角と文字はSVGで描画しており、その中にsvgのimageエレメントを使用してCanvasの図を挿入しています。
本ページを拡大するとわかりますが、中のマンデルブロは拡大するとギザギザが目立ちますが、外の文字は、SVGで描画しているため綺麗であることがわかります。
また、IEの場合、右クリックでSVGとCanvasのイメージを一つのSVGファイルとして保存することができます。
CanvasオブジェクトはjavascriptにcreateElementで動的に作成しています。
マンデルブロには複素座標(-1.33,-1)-(1.33,1)の範囲を320*240ピクセルの大きさで最大反復回数64回でJavascriptによりCanvas領域に描画しています。
素のCanvasには点を描画する関数が無いので1ピクセルの大きさの四角形で代用しています。
Canvasの描画内容は、toDataURLによりpng形式でBase64に変換し、それをsetAttributeにより直接imageタグでファイル名の代わりにxlink:hrefのプロパティを書き換えて取り込んでいます。
マンデルブロについては、マンデルブロ描画プログラムVersion2.3を参照してください。
四角形の描画方法については、Canvasによる長方形の描画サンプルを参照してください。
図の下には描画に要した時間が表示されます。
(0,0) (320,240)

以下に環境による実行速度の例を示します。
CPU Windows ブラウザ 実行速度
Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz Windows 10 Edge 44.17763.1.0(64bit) 173ms
Intel(R) Core(TM) i5-4300U CPU @ 1.90GHz Windows 8.1 InternetExplorer 11 11.0.9600.19236 254ms
Intel(R) Core(TM) i7-3820 CPU @ 3.60GHz(OC4.2GHz) Windows 7 InternetExplorer 11 11.0.9600.18638 230ms
Intel(R) Celeron(R) CPU G3900 @ 2.80GHz Windows 10 Edge 25.10586.0.0(64bit) 166ms
Intel(R) Celeron(R) CPU G3900 @ 2.80GHz Windows 10 IE 11 11.306.10586.0(64bit) 1077ms
Intel(R) Celeron(R) CPU G3900 @ 2.80GHz Windows 10 Chrome 58.0.3029.96(64bit) 153ms
Intel(R) Celeron(R) CPU G3900 @ 2.80GHz Windows 10 Firefox 53.0(32bit) 172ms

ソースコード

本ページからCanvasによるマンデルブロ描画にかかわる部分のみを抽出したhtmlのソースコードを以下に示します。
htmlのソースコードは本ページの最後のリンクよりダウンロードすることができます。
<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head>
  <meta charset="utf-8"/>
  <title>SVGにCanvasを描画するサンプル</title>
</head>

<body> 
  <svg width="360" height="280"  viewBox="-20 -20 360 280" xmlns="http://www.w3.org/2000/svg">
    <rect x="-20" y="-20" width="360" height="280" fill="none" stroke="blue" />
    <text x="-20" y="-4" font-size="14" stroke="blue">(0,0)</text>
    <text x="270" y="254" font-size="14" stroke="blue">(320,240)</text>
    <image x="0" y="0" width="320" height="240" id="c1" xlink:href="" >
  </svg>

<script type="text/javascript">

// マンデルブロ描画
function mandelbrot(ctx,wx,wy,amin,bmin,amax,bmax){
  var a,b,c;
  var sx,sy;
  sy=wy-1;
  for(b=bmin;b<bmax;){
    sx=0;
    for(a=amin;a<amax;){
      var x=0;
      var y=0;
      for(c=0;c<64;c++){
        var x2=x*x;
        var y2=y*y;
        var zx=x2-y2-a;
        var zy=2*x*y-b;
        x=zx;
        y=zy;
        if(4<=x2+y2)
          break;
      }
      var r1=(c & 0x3)<<6;
      var g1=(c & 0xc)<<4;
      var b1=(c & 0x30)<<2;
      ctx.fillStyle = 'rgb(' +r1+','+g1+','+b1+ ')';
      ctx.fillRect(sx,sy,1,1);
      a+=(amax-amin)/wx;
      ++sx;
    }
    b+=(bmax-bmin)/wy;
    --sy;
  }
}

window.onload = function(){
  var canvas = document.createElement('canvas');
  canvas.width=320;
  canvas.height=240;
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');
    mandelbrot(ctx,320,240,-1.33,-1,1.33,1);
    var png=canvas.toDataURL();
    document.getElementById("c1").setAttribute('xlink:href',png);
  }
}
</script>

</body>
</html>
ソースファイルのダウンロード(mandelbrot2.zip)