html5 でグラフ(図)を描く

■ html5 でグラフを描く ( canvas, SVG )

 Html5 では、canvas や SVG を使って図表を描くことが出来ます
これらを使うと、従来は Flash などを使っていた図形の描画やアニメーションを作ることができます
canvas と SVG の大きな違いは描画形式で、比較すると次のようになります。参考
canvasSVG
描画形式ラスター形式ベクター形式
描画方法キャンバスに JavaScript等を用いて描画<svg>タグの子要素として記載
特徴ピクセル単位での細かい描画を行う拡大、縮小で図形の劣化が少なく、変形も容易
好適対象微細描画の複雑な組合せ
固定描画
円、四角形などの単純図形の組み合わせ
動的描画
記述例【html】
<canvas id='canvas' width='200' height='200'>
</canvas>
【JavaScript】
var canvas=document.getElementById('canvas');
var context=canvas.getContext('2d');
context.fillStyle='rgb(0,0,255)';
context.fillRect(0,0,100,100);
【html】
<svg width='200' height='100' viewBox='0 0 200 150'>
  <circle id='circ' cx='50' cy='80' r='20' fill='#3d3' />
</svg>
【JavaScript】
var crc = document.getElementById('circ');
crc.addEventListener('click', function() {
  crc.setAttribute('r', '40');
});
ライブラリwebopixelGraphicsJS
* canvas画像は、img要素(url)に変換することも出来ます

■ Canvas -html5

 HTML5 では、新たに追加された canvas 要素(既定値:300px*150px)で、図形の描画ができます。
<canvas>~</canvas> の矩形領域に JavaScript で記述した線や画像やグラフを表示できます。
 まず、具体的な例を示してみましょう。 他の例
    【 記 述 例 】 ↓
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>sample110</title>
  <script type="text/javascript">
    <!--
      window.onload = function() {
        var cv= document.getElementById('cvs');  //id 名の要素を取得
        var ctx= cv.getContext('2d');            //2D(平面) Contextを取得
        if(!cv||!cv.getContext){return false;}
        //左から10上から5の位置に幅30高さ70の矩形板を描く
        ctx.fillRect(10,5,30,70);
        //中心 x=60,y=25,半径40の青色半円板を反時計回りで描く
        ctx.fillStyle = '#0000ff';               //充填色を指定
        ctx.arc(60,25,40,Math.PI,Math.PI*2,true);//円弧を記述
        ctx.fill();                              //円弧を表示
        // 各点を結んで、緑色 '#00ff00' の三角枠を描画する 
        ctx.beginPath();                         //パスをクリア
        ctx.strokeStyle = '#00ff00';             //枠線色を指定
        ctx.moveTo(70, 10);                      //始点に移動
        ctx.lineTo(20, 90);
        ctx.lineTo(110, 80); 
        ctx.lineTo(70,10);
        ctx.stroke();                            //枠線を表示
        //中心座標 x=80,y=65,半径30の赤色,透明度0.6の円板を描く
        ctx.beginPath();                         //パスをクリア
        ctx.fillStyle = 'rgba(255,0,0,0.6)';     //充填色,透明度を指定
        ctx.arc(80,65,30,0,Math.PI*2,false);     //円を記述
        ctx.fill();                              //円板色で充填
      }
    // -->
  </script>
</head>
<body style="background-color: #ffffdd;">
  <canvas id="cvs" width="140" height="100">
    ここに HTML-5 対応の図形を表示
  </canvas>
</body>
</html>

■ 上記サンプルの解説 -canvas

  1. HTML の記述
    HTML の <body> 内の図形を表示する位置に、<canvas ~>・・・</canvas> (上記 36-38行目)を記述します
    canvas 内には、要素のID名 (id) とその領域の幅 (width) と高さ (height) をピクセル値で記述します。(36行目)
  2. JavaScript の記述
    1. 図形を表現する JavaScript を head 内などに記述します。( 6-33行目)
    2. JavaScript を head 内に記述したため、window.onload = function() { ・・・で呼び出します。( 8行目)
    3. IDで指定した要素を取得し、その 2D Context(制御情報)を取得します。無いときは中止します。( 9-11行目)
                        var cv= document.getElementById('cvs');   //id 名の要素を取得
                        var ctx= cv.getContext('2d');             //2D(平面) Contextを取得
                        if(!cv||!cv.getContext){return false;}
                      
    4. 塗りつぶし矩形板を描画する。fillRect(x,y,幅,高さ) (13行目)
                        ctx.fillRect(10,5,30,70);
                      
    5. 円弧 arc(x,y,半径,始点角,終点角,反時計回り)を青色 '#0000ff'で充填。(15-17行目)
                        ctx.fillStyle = '#0000ff';               //充填色を指定
                        ctx.arc(60,25,40,Math.PI,Math.PI*2,true);//円弧を記述
                        ctx.fill();                              //円弧を表示
                      
    6. beginPath() で前パスをクリアし、各点を結んで緑色 '#00ff00' の三角枠を描画します。(19-25行目)
                        ctx.beginPath();                         //パスをクリア
                        ctx.strokeStyle = '#00ff00';             //枠線色を指定
                        ctx.moveTo(70, 10);                      //始点に移動
                        ctx.lineTo(20, 90);
                        ctx.lineTo(110, 80); 
                        ctx.lineTo(70,10);
                        ctx.stroke();                            //枠線を表示
                     
    7. 前パスをクリアし、充填色 rgba(赤,緑,青,透明度) を指定し、円板を描画します。(27-30行目)
                        ctx.beginPath();                         //パスをクリア
                        ctx.fillStyle = 'rgba(255,0,0,0.6)';     //充填色,透明度を指定
                        ctx.arc(80,65,30,0,Math.PI*2,false);     //円を記述
                        ctx.fill();                              //円板色を充填
                      
  3. つまり <canvas> で、図形を描くには、
    1. html タグ内に、<canvas id="**" width="xx" height="yy"></canvas>のように 図形を描く id属性を指定して、
    2. JavaScript に、var cv= document.getElementById('**'); var ctx= cv.getContext('2d'); と記述し、スクリプトと描画領域とを関連付けた後、
    3. JavaScript 内に描画図形の詳細を記述して、
    4. 対応する <canvas> に図形を表示します。
    このように、従来は flash などで描いていた図形を JavaScript を使って描き込むことができるわけです。
    これは Google Maps API などと似た手法と言えます。 なおグラフを描くなら、Google Chart 等もあります。

■ 色々な図形 -canvas

 以上の例で、canvas 要素で、図形の描画領域を確保し、その領域に JavaScript を駆使して色々な図形が描けることが解ります。
 以下で、色々な例を示し置きます。記述の詳細は、Canvas 2Dリファレンスを参照下さい
  【グラフ描画】-canvas 参考
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>折れ線グラフ</title>
  <style>
    body { background: #fafafa; }
    canvas { display:block; background:#ffe; margin:0 auto; }
  </style>
  <script type="text/javascript">
      //  var datas = [5,30,20,80,40,100,70];
      var datas = [0.4, 0.2, 1, 0.3, 0.4, 0.7];
    yMax = Math.max.apply({}, datas);
    window.onload = function() {
      var cv1 = document.getElementById('cvs1');
      var ctx = cv1.getContext('2d');
        if (!cv1||!cv1.getContext) { return false; }
      var spcW=40;            // Y軸左のスペース
      var spcH=30;            // X軸下のスペース
      var groundW= cv1.getAttribute("width")-spcW; // グラフ領域W
      var groundH= cv1.getAttribute("height")-spcH;// グラフ領域H
      var groundX0= spcW; var groundY0= groundH;   // 原点位置
      var pichX = groundW/datas.length;            // X目盛ピッチ
      DmYMx = Math.pow(10,Math.ceil(Math.log(yMax)/Math.log(10)));
        var cnstH= 210/DmYMx;
        pichH = DmYMx/4;                           //Y目盛ピッチ   
        ctx.beginPath();                  //現在のパスをリセット
        ctx.save();                       //現在の描画条件を保管
        // タイトル描画
        ctx.textAlign = "center";
        ctx.textBaseline = "top";
        ctx.font = "12pt Arial";
        ctx.fillStyle = "rgb(0,0,180)";
        ctx.fillText('グラフタイトル',groundX0-10+0.5*groundW, 5 );
        ctx.restore();                    //描画条件を元に戻す
        ctx.save();                       //現在の描画条件を保管
        // X軸描画
        ctx.textAlign = "center";
        ctx.textBaseline = "top";
        ctx.strokeStyle = "rgb(0,0,0)";
        ctx.moveTo( groundX0, groundY0 );
        ctx.lineTo( groundX0+groundW-20, groundY0 );
        for (var i = 0; i < groundW/pichX; i++){
          ctx.moveTo( groundX0+i*pichX, groundY0 );
          ctx.lineTo( groundX0+i*pichX, groundY0-5 );
          ctx.fillText(i,groundX0+i*pichX,groundY0+2 );
        }
        ctx.fillText('X軸',0.5*groundW+groundX0,groundY0+15 );
        // Y軸描画
        ctx.moveTo( groundX0, groundY0 );
        ctx.lineTo( groundX0, 25 );
        ctx.textAlign = "end";
        ctx.textBaseline = "middle";
        for (var i = 0; i < groundH/pichH/cnstH-1; i++){
          ctx.moveTo( groundX0, groundY0-i*pichH*cnstH );
          ctx.lineTo( groundX0+5, groundY0-i*pichH*cnstH );
          ctx.fillText(i*pichH,groundX0-3,groundY0-i*pichH*cnstH );
        }
        ctx.rotate(-0.5* Math.PI);
        ctx.fillText('Y軸',-0.45*groundY0,groundX0-30 );
        ctx.stroke();                     //サブパスを描画
        ctx.restore();                    //描画条件を元に戻す
        ctx.save();                       //現在の描画条件を保管
        ctx.beginPath();                  //現在のパスをリセット
        // line
        ctx.fillStyle = "rgb(0,180,0)";
        ctx.strokeStyle = "rgb(0,180,0)";
        for (var i = 0; i < datas.length; i++){
          ctx.moveTo(groundX0+i*pichX, groundY0-cnstH*datas[i]);
          if (i!=0){ ctx.lineTo(groundX0+(i-1)*pichX, groundY0-cnstH*datas[i-1]);}
          ctx.fillRect(groundX0+i*pichX-2, groundY0-cnstH*datas[i]-2,4,4);
          ctx.textBaseline = "bottom"; ctx.textAlign = "center";
          ctx.fillText(datas[i], groundX0+i*pichX, groundY0-cnstH*datas[i]);
        }
        ctx.stroke();                     //サブパスを描画
        ctx.restore();                    //描画条件を元に戻す
    }; // end of onload -----------------------
  </script>
</head>
<body>
  <canvas id="cvs1" width="360" height="300"></canvas>
</body>
</html>

  【アナログ時計】 -canvas 参考
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <style>
    canvas { display:block; width:300px; height:300px; background:#ed9; margin:0 auto; }
  </style>
  <script>
    window.onload = function() { init(); };           // ページ読み込み時に init()を実行
    function init(){ clock(); setInterval('clock();',1000); } // clock()を1秒周期で実行
    function clock(){ 
      var now = new Date(); 
      var canvas = document.getElementById("clockid");
      var ctx = canvas.getContext('2d');
      ctx.save();
      // 設定
      canvas.width = 300; canvas.height = canvas.width;
      var w = canvas.width; var h = canvas.height;
      var center = { x: 0.5*w, y: 0.5*h };
      var rads = 0.4*w;            // 文字盤の数字の中心までの半径
      ctx.clearRect(0, 0, w, h);   // 表示域クリア
      // 文字盤設定
      ctx.save();
      ctx.font = "30px 'sans-serif'";
      ctx.textAlign   ="center";
      ctx.textBaseline ="middle";
      ctx.fillStyle   = "rgb(0, 0, 0)";
      ctx.shadowBlur = 5;
      for (var i = 0; i < 12; i++) {
        var radian = i * Math.PI / 6;
        var x = center.x + rads * Math.sin(radian);
        var y = center.y - rads * Math.cos(radian);
        var text = "" + (i == 0 ? "12" : i);
        ctx.fillText(text, x, y);
      }
      ctx.restore();
      //  中心を移動
      ctx.translate(center.x,center.y);
      // 分目盛
      ctx.save();
      ctx.strokeStyle = "rgb(170,170,170)";
      ctx.lineWidth = 2;
      ctx.beginPath();
      for (var i=0;i<60;i++){
        if (i%5!=0){ ctx.moveTo(100,0); ctx.lineTo(95,0); }
        ctx.rotate(Math.PI/30);
      }
      ctx.stroke();
      // 時間目盛
      ctx.strokeStyle = "rgb(100,100,100)";
      ctx.lineWidth = 3;
      ctx.beginPath();
      for (var i=0;i<60;i++){
        ctx.moveTo(100,0);
        ctx.lineTo(85,0);
        ctx.rotate(Math.PI/6);
      }
      ctx.stroke();
      ctx.restore();
      // 針の設定
      var sec = now.getSeconds();
      var min = now.getMinutes();
      var hr= now.getHours();
      hr = hr>=12 ? hr-12 : hr; // 12以上なら「hr-12」、それ以外は「hr」
      ctx.fillStyle = "rgb(160, 160,160)";
      // 短針設定
      ctx.save();
      ctx.rotate( hr*(Math.PI/6)+ (Math.PI/360)*min+ (Math.PI/21600)*sec )
      ctx.lineWidth = 7;
      ctx.shadowBlur = 5;
      ctx.shadowColor = "rgb(90,90,90)";
      ctx.beginPath();
      ctx.moveTo(-3,25);
      ctx.lineTo(0,-70);
      ctx.lineTo(3,25);
      ctx.stroke();
      ctx.restore();
      // 長針設定
      ctx.save();
      ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
      ctx.lineWidth = 4;
      ctx.strokeStyle = "rgb(0, 0, 0)";
      ctx.shadowBlur = 10;
      ctx.shadowColor = "rgb(160, 160,160)";
      ctx.beginPath();
      ctx.moveTo(-2,25);
      ctx.lineTo(0,-99);
      ctx.lineTo(2,25);
      ctx.stroke();
      ctx.restore();
      // 秒針設定
      ctx.save();
      ctx.rotate(sec * Math.PI/30);
      ctx.strokeStyle = "rgb(207, 170, 77)";
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(0,30);
      ctx.lineTo(0,-107);
      ctx.stroke();
      ctx.restore();
      // 時計の中心の円板
      ctx.save();
      ctx.beginPath();
      ctx.lineWidth = 3;
      ctx.strokeStyle = "rgb(207, 170, 77)";
      ctx.fillStyle   = "rgb(200, 160, 70)"; 
      ctx.arc(0,0,5,0,Math.PI*2,true);
      ctx.stroke();
      ctx.fill();
      ctx.restore();
    };   // end of clock() --------------------
  </script>
</head>
<body>
  <canvas id="clockid"></canvas>
</body>
</html>

  【スミスチャート】 -canvas  参考
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Smith Chart</title>
  <style>
    #SMcvsRapper{ margin:0px auto; text-align:center; background:#eef; width:440px; height:410px; }
    #SMcvs{ border:0px solid #CCC; background:#ff9; width:100%; height:100%; }
  </style>
  <script type="text/javascript">
    <!-- 
      // ### r+jx=(1+u+jv)/(1-u-jv) ###
      // ### (u-r/(r+1))^2+v^2=1/(1+r)^2  (u-1)^2+(v-1/x)^2=1/x^2 ###
      var SMcv;                   // canvas要素(HTMLCanvasElement)
      var SMctx;                  // 2Dコンテキスト(CanvasRenderingContext2D)
      var SMr0=200;               //円の半径(px)
      var SMcvHg = 5;             // 円の縦幅余白(px)
      var SMcvH= 2*(SMr0+SMcvHg); // SMcvの縦幅(px)
      var SMcvWg = 20;             // 円の横幅余白(px)
      var SMcvW = 2*(SMr0+SMcvWg); // SMcvの横幅(px)
      var SMmouseX;               // 最後にクリックされた位置のx座標
      var SMmouseY;               // 最後にクリックされた位置のy座標
      var SMtxtP=[
                   [0,0,0,0,0,0,0],
                   [0.2,0.37,0.05,0.6,1.44,1.57,1.84],
                   [0.5,0.67,0.36,0.2,1.84,1.27,1.54],
                   [1,1,1,0.08,1.96,1,1],
                   [2,1.27,1.55,0.2,1.83,0.7,0.39],
                   [5,1.57,1.85,0.62,1.42,0.4,0.09],
                   [10,1.69,1.89,0.8,1.24,0.25,0.01]
                ];
      
      function init(){
        SMcv=document.getElementById('SMcvs'); //id 名の要素を取得
        SMcv.width = SMcvW;
        SMcv.height = SMcvH;
        SMctx=SMcv.getContext('2d');           //2D(平面) Contextを取得
        if(!SMcv||!SMcv.getContext){return false;}
        SMcy0=SMr0+SMcvHg;SMcx0=SMr0+SMcvWg;   // 中心位置
        drawSMTH();                            // smith chart を描画
        SMctx.fillText('ここに Γを記載',5,15);
        SMcv.onclick = function(SMe){          // クリックイベントの登録
          SMctx.clearRect(0, 0, SMcvW, SMcvH); // 一度描画をクリア
          drawSMTH();                          // smith chart を描画
          // クリック位置の座標計算(canvasの左上を基準。border分は0)
          var SMrect = SMe.target.getBoundingClientRect();
          SMmouseX= SMe.clientX- Math.floor(SMrect.left)- 0;
          SMmouseY= SMe.clientY- Math.floor(SMrect.top)- 0;
//   alert(SMmouseX+', '+SMmouseY);       
          // クリック位置を中心に円を描画
          SMctx.beginPath();
          SMctx.arc(SMmouseX,SMmouseY,3,0,Math.PI*2,false);
          SMctx.fill();
          // 座標の表示テキストを描画
          var SMmaxWidth = 100;
          SMctx.textAlign = 'start';
          SMmouseSMX=(SMmouseX-0.5*SMcvW)/SMr0;
          SMmouseSMY=(-SMmouseY+0.5*SMcvH)/SMr0;
          var SMrefA = Math.round(Math.sqrt(SMmouseSMX*SMmouseSMX+ SMmouseSMY*SMmouseSMY)*1000)/1000;
          var SMrefP = Math.round(Math.atan2(SMmouseSMY,SMmouseSMX)*1800/Math.PI)/10;
          var SMmessage = 'Γ:'+ SMrefA + ', ∠:'+ SMrefP +'度';
        if(SMrefA>1){SMmessage= 'そこは受動回路外です'; };
          SMctx.fillText(SMmessage,5,15);
        }; // end of SMcv.onclick  --------------
      };   // end of initial()  -----------------
      
      function drawSMTH(){                     // smith chart を描画
        SMctx.lineWidth=1; SMctx.strokeStyle='#c96';      //線の太さ、色指定
        SMctx.beginPath();                     // 現在のパスをリセット
        SMctx.moveTo(SMcvWg,SMcy0); SMctx.lineTo(2*SMcx0-SMcvWg,SMcy0); //横線を引く
        SMctx.arc(SMcx0,SMcy0,SMr0,0, Math.PI*2, false); // 外円を描画する        
        for(j=1;j<SMtxtP.length;j++){          //等インピーダンス線を描く
          SMzz=SMtxtP[j][0];                   // パラメータセット
          SMcx=SMcx0+SMr0*SMzz/(1+SMzz);SMcy=SMcy0;
          SMr=SMr0/(1+SMzz);                              //等抵抗円半径を設定
          SMctx.moveTo(SMcx0+SMr0,SMcy0);                 //z=∞点に移動
          SMctx.arc(SMcx,SMcy0,SMr,0,2*Math.PI,true);     //等抵抗円を描く
          SMcx=SMcx0+SMr0; SMr=SMr0/SMzz; SMcy=SMcy0-SMr; //等インダクタンス半径設定
          SMctx.moveTo(SMcx0+SMr0,SMcy0);                 //z=∞点に移動
          var SMangEnd = 0.5*Math.PI+ 2* Math.atan(SMzz);
          SMctx.arc(SMcx,SMcy,SMr,0.5*Math.PI,SMangEnd,false); //等インダクタンス弧
          SMcx=SMcx0+SMr0; SMr=SMr0/SMzz; SMcy=SMcy0+SMr; //等キャパシタンス半径設定
          SMctx.moveTo(SMcx0+SMr0,SMcy0);                 //z=∞点に移動
          var SMangEnd =1.5*Math.PI- 2* Math.atan(SMzz);
          SMctx.arc(SMcx,SMcy,SMr,1.5*Math.PI,SMangEnd,true);  //等キャパシタンス弧
        }
        SMctx.stroke();                                  // 現在のサブパスに線を引く
        SMctx.font = "11.5px 'MS ゴシック'";           //目盛のフォント
        SMctx.textAlign = "middle";
        SMctx.fillText("SmithChart",1.71*SMcx0,0.06*SMcy0);    //タイトル
        SMctx.fillText("byくらげ",1.76*SMcx0,1.96*SMcy0);      //作者
        SMctx.fillText("0",0.05*SMcx0,1.02*SMcy0);
        SMctx.fillText("∞",1.92*SMcx0,1.02*SMcy0);
        for(j=1;j<SMtxtP.length;j++){
          SMctx.fillText(SMtxtP[j][0],SMtxtP[j][1]*SMcx0,0.99*SMcy0);
          SMctx.fillText(SMtxtP[j][0]+'j',SMtxtP[j][2]*SMcx0,SMtxtP[j][3]*SMcy0);
          SMctx.fillText('-'+SMtxtP[j][0]+'j',SMtxtP[j][2]*SMcx0,SMtxtP[j][4]*SMcy0);
        }
        SMctx.stroke();                                   // 現在のサブパスに線を引く
      }; // end of drawSMTH()  ---------------------
    // -->
  </script>
</head>
<body onload="init()">
  <div id="SMcvsRapper">
    <canvas id="SMcvs" width='440' height='410'>ここに、チャートを表示</canvas>
  </div>
</body>
</html>

  【環状メニュー】 -canvas-で 24分割環状メニューを作ってみました
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <script type="text/javascript">
    var sekki = ['立春','雨水','啓蟄','春分','清明','穀雨','立夏','小満','芒種','夏至','小暑','大暑','立秋','処暑','白露','秋分','寒露','霜降','立冬','小雪','大雪','冬至','小寒','大寒'];
    var sekkiurl =  ['https://kurage.ready.jp/','https://kurage.ready.jp/jhp_g/html5/canvas.html','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','https://kurage.ready.jp/jzatsu/canvsG.html'];
    var bkcolor=['#c66','#6c6','#66c','#cc6','#6cc','#c6c'];
    var centx = 200; var centy = 200;
    var rout = centx; var rc = rout-30;  var rin = rout-65; 
    function onload() {
      var canvas = document.getElementById('sample');
      if (!canvas) { return; }
      var ctx1 = canvas.getContext('2d');          // 2D(平面)コンテキストを得る
      if (!ctx1) { return; }
      ctx1.translate( centx,centy );               // 中心座標にシフト
      ctx1.font = " 22px Arial, meiryo, sans-serif";  // フォントを設定
      ctx1.fillText('24節季リンク', -70, 10 ); 
      for ( i=0; i<sekki.length; i++ ){
        ctx1.rotate( i*Math.PI / 12 );       // 座標を回転する
        buildPath(i);
        ctx1.fillStyle = bkcolor[i % bkcolor.length];
        ctx1.fill();
        ctx1.fillStyle = "#fff" ;            // テキストの色
        var txt1 =  sekki[i].charAt(0);      // 漢字一文字目取得
        var txt2 =  sekki[i].charAt(1);      // 漢字二文字目取得
        ctx1.fillText( txt1, -12, -rc-3);    // 一文字目位置指定
        ctx1.fillText( txt2, -12, -rc+23);   // 二文字目位置指定
        ctx1.rotate( -i*Math.PI / 12 );      // 座標角度を戻す
      };  //  for i<sekki.length --------------------

      canvas.onclick = function(e) {
          var x = event.clientX + window.pageXOffset - canvas.offsetLeft;
          var y = event.clientY + window.pageYOffset - canvas.offsetTop;
          for ( i=0; i<sekki.length; i++ ){  
            ctx1.rotate( i*Math.PI / 12 );   // 座標を回転する
            buildPath(i);
            if(ctx1.isPointInPath(x, y)) {
              ctx1.stroke();
              alert( sekki[i] + 'をクリック');
              location.href = sekkiurl[i];
            }
            ctx1.rotate( -i*Math.PI / 12 );  // 座標角度を戻す
          };  //  for i<sekki.length --------------------
      };  //  canvas.onclick  ---------------

      function buildPath(i) {
        ctx1.beginPath();
        ctx1.arc( 0,0, rout, -98 * Math.PI / 180, -83 * Math.PI / 180, false); // 外弧
        ctx1.arc( 0,0, rin, -83 * Math.PI / 180, -98 * Math.PI / 180, true);   // 内弧
        ctx1.closePath();                    // 扇状台形作成
      }; //  buildPath()  --------------------
    }; //  onload()()  --------------------
  </script>
</head>
<body onLoad="onload()">
  <canvas width="400" height="400" id="sample" style="background:#eee; padding:5px 10px; "></canvas>
</body>
</html>

  【アニメーションの例】 -canvas-で ブロック移動のアニメーションを作ってみました。参考
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <style>
    #canvas { background-color: #ddd; }
  </style>
<head>
<body>
  <canvas  id="canvas" width="400" height="400"></canvas>
  <script>
    window.addEventListener('load', draw, false);
    function draw(){
      var x = 0, y = 0, z = 20;
      var step0 = 3,  step = step0;    
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      var ctxwd = canvas.width;
      var ctxht = canvas.height;
      function loop() {
        ctx.clearRect(0 ,0, ctxwd, ctxht); //キャンバスをクリア
        x +=step;
        y +=step;
        ctx.beginPath();
        ctx.fillStyle = 'green';
        ctx.fillRect(200, y, z, z);  // 縦移動矩形
        ctx.fillStyle = 'blue';
        ctx.fillRect(x, y, z, z);    // 斜移動矩形  
        ctx.fillStyle = 'brown';
        ctx.arc(x+10, 300, 10, 0, 2*Math.PI, false); // 横移動円板  
        ctx.fill();
        if (y >= (ctxht-z)) {
           step = -step0;
        } else if (y <= 0) {
           step = step0;
        }    
        requestAnimationFrame(loop);  // 描画処理の実行調節
      }
      loop();
    } 
  </script> 
</body>
</html>

■ canvas リンク

リファレンス
サンプル
Canvas 全般
Canvasのimg要素化
その他

■ 色々な図形 -SVG

 HTML5 では、svg を読み込むことも、HTML 中に図形を直接描画することもできます。 後者の場合 <svg>~</svg> 領域内にタグを記述します。
 注.<svg>内は XML ベースのテキストファイルとなりますので、終了タグを持たないタグは 『/>』で閉じます。
    【 記 述 例 】 ↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
</head> 
<body style="background: #eff;">
  <svg width="140" height="100" viewBox="0 0 140 100">
    <!-- 左から10上から5の位置に幅30高さ70の矩形板を描く -->
    <rect x="10" y="5" width="30" height="70" fill="#000000" />
    <!-- 始点(20,25);半径(40,40);傾き(0度);短弧(0);反時計回り(0);dx(80);dy(0)で青色半円板を描く -->
    <path stroke="blue" stroke-width="1" fill="blue" d="M 20 25 a 40 40 0 0 0 80 0 z"/>
    <!-- 各点を結んで、緑色 '#00ff00' の三角枠を描画する -->
    <polygon points="70,10 20,90 110,80 70,10" fill="none" stroke="#00ff00" />
    <!-- 中心座標 x=80,y=65,半径30の赤色,透明度0.6の円板を描く -->
    <circle cx="80" cy="65" r="30" fill="#ff0000" opacity="0.6"/>
  </svg><br>
  <img src="sample01.svg" width=100 height=60> <!-- svg画像ファイルを追加 -->
</body></html>

【 読込用 svg画像ファイル: sample01.svg 】
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <rect x="0" y="0" width="100" height="60" fill="#ddd" />
  <polygon points="50 5, 90 30, 50 55, 10 30" fill="#63d" />
  <text x="50" y="37" font-size="20" text-anchor="middle" fill="white">SVG</text>
</svg>


 他の色々な例も示し置きます。
  【グラフの描画】-svg 参考
<!DOCTYPE html>
<html>
<head><title>サイズ変更しやすい SVG グラフ - 研究に使うポスグレ</title>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
  <script language="JavaScript">
    <!--
      function SVGline(){
        var cnt = document.getElementById('conta');
        var vwBXx=cnt.offsetWidth; var vwBXy=cnt.offsetHeight;
        var viewBX ='0 0 480 350';        // 0 0 vwBXx vwBXy
        var x0 = 70;  var y0 = vwBXy-50;  // グラフ原点   70 300
        var x1 = vwBXx-30;  var y1 = 40;  // グラフ右上  450  40
        var xrng= x1-x0; var yrng= y0-y1; // グラフ領域  380 260
        var xlab ='X 軸'; var ylab ='Y 軸'; var titl ='グラフタイトル';
        var fsize =[12,18,26];            // 目盛・ラベル・タイトル
        var xys= [[0,0.4],[1,0.2],[2,0.7],[3,0.3],[4,0.4],[5,1]];
        var ww = 5;  var hh = 1;          // 横max 縦max
        var wwN = 5;  var hhN = 5;        // 横分割数 縦分割数
        var fx= xrng/ww; var fy= yrng/hh; // 表示比係数
        
        var uri = "http://www.w3.org/2000/svg";
        var svg1 = document.createElementNS(uri, 'svg');
        svg1.setAttribute('width', vwBXx);
        svg1.setAttribute('height', vwBXy);
        svg1.setAttribute('viewBox',viewBX);
        svg1.setAttribute('style',"background:#dfb;");
        cnt.appendChild(svg1);            // svg1 をcnt に組込む
        var g1 = document.createElementNS(uri, 'g');  
        svg1.appendChild(g1);             // グループg1 の組込み

        // グラフ枠 
        var rect = document.createElementNS(uri, 'rect');
        rect.setAttribute('x', x0);
        rect.setAttribute('y', y1);
        rect.setAttribute('width', x1-x0);
        rect.setAttribute('height',y0-y1);
        rect.setAttribute('fill', '#ffe');
        rect.setAttribute('stroke', 'black');
        g1.appendChild(rect);             // 枠の組込み
        
        // タイトル
        var txt = document.createElementNS(uri, 'text');
        txt.textContent = titl;
        txt.setAttribute('text-anchor', 'middle');
        txt.setAttribute('font-size',fsize[2]);
        txt.setAttribute('fill', 'blue');
        txt.setAttribute('x',x0+xrng/2);
        txt.setAttribute('y',30);
        g1.appendChild(txt);              // タイトルの組込み
        
        // x軸 ラベル・目盛
        var txt = document.createElementNS(uri, 'text');
        txt.textContent = xlab;
        txt.setAttribute('text-anchor', 'middle');
        txt.setAttribute('font-size',fsize[1]);
        txt.setAttribute('x',x0+xrng/2);
        txt.setAttribute('y', y0+40);
        g1.appendChild(txt);              // x軸 ラベルの組込み

        for (var i = 0; i <=wwN; i++) {
          var txt= document.createElementNS(uri,'text');
          txt.setAttribute('x', x0+i*ww/wwN*fx);
          txt.setAttribute('y', y0+15);
          txt.setAttribute('dominant-baseline', 'middle');
          txt.setAttribute('text-anchor', 'middle');
          txt.setAttribute('font-size',fsize[0]);
          txt.textContent = i*ww/wwN;
          g1.appendChild(txt);
          var lin = document.createElementNS(uri, 'line');
          lin.setAttribute('x1', x0+i*ww/wwN* fx);
          lin.setAttribute('y1', y0);
          lin.setAttribute('x2', x0+i*ww/wwN* fx);
          lin.setAttribute('y2', y0-5);
          lin.setAttribute('stroke', 'blue');
          g1.appendChild(lin);
        };                                // x軸 目盛の組込み

        // y軸 ラベル・目盛
        var txt = document.createElementNS(uri,'text');
        txt.textContent = ylab;
        txt.setAttribute('text-anchor', 'middle');
        txt.setAttribute('font-size', fsize[1]);
        txt.setAttribute('x', x0-40);
        txt.setAttribute('y', y0/2 );
        txt.setAttribute('transform','rotate(-90,'+(x0-40)+','+y0/2+')');
        g1.appendChild(txt);              // y軸 ラベルの組込み

        for (var i = 0; i <=hhN; i++) {
          var txt = document.createElementNS(uri, 'text');
          txt.setAttribute('x', x0-5);
          txt.setAttribute('y', y0-i*hh/hhN*fy);
          txt.setAttribute('dominant-baseline', 'middle');
          txt.setAttribute('text-anchor', 'end');
          txt.setAttribute('font-size', fsize[0]);
          txt.textContent = i*hh/hhN;
          g1.appendChild(txt);
          var lin = document.createElementNS(uri, 'line');
          lin.setAttribute('x1', x0);
          lin.setAttribute('y1', y0-i*hh/hhN* fy);
          lin.setAttribute('x2', x0+5);
          lin.setAttribute('y2', y0-i*hh/hhN* fy);
          lin.setAttribute('stroke', 'black');
          g1.appendChild(lin);
        };                                // y軸 目盛の組込み
    
        // data plot
        for (var i = 0; i < xys.length; i++) {
          var cir = document.createElementNS(uri, 'circle');
          cir.setAttribute('cx', x0+xys[i][0]*fx);
          cir.setAttribute('cy', y0-xys[i][1]*fy);
          cir.setAttribute('r', 3);
          cir.setAttribute('fill', '#3c3');
          g1.appendChild(cir);            // ドット表示
          var txt = document.createElementNS(uri, 'text');
          txt.setAttribute('x',x0+xys[i][0]*fx);
          txt.setAttribute('y',y0-xys[i][1]*fy-6);
          txt.setAttribute('dominant-baseline', 'middle');
          txt.setAttribute('text-anchor', 'middle');
          txt.setAttribute('font-size', fsize[0]);
          txt.setAttribute('fill', '#3c3');
          txt.textContent = xys[i][1];
          g1.appendChild(txt);            // 値表示
        }
        var pat = document.createElementNS(uri, 'path');
        var dpat= 'M '+(x0+xys[0][0])+', '+(y0-xys[0][1]*fy);
        for (var i = 1; i < xys.length; i++) {
          dpat += ' '+(x0+xys[i][0]*fx)+', '+(y0-xys[i][1]*fy);
        }
        pat.setAttribute('d', dpat);
        pat.setAttribute('stroke', '#3c3');
        pat.setAttribute('stroke-width', '1');
        pat.setAttribute('fill', 'none');
        g1.appendChild(pat);              // ライン接続
      };
    //-->
  </script>
  <style>
    #wrap{ background:#3ba; width:482px; height:350px; margin:auto;}
    #conta{ width:480px; height:350px; margin:auto; background:#dff; }
  </style>
</head>
<body onload="SVGline()">
  <div id="wrap">
    <div id="conta" width="480" height="350"></div>
  </div>
</body>
<html>


  【アナログ時計】 -SVG 参考
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
  <style type="text/css">
    #boad{ width:320px; height:304px; margin:0 auto; text-align:center; }
    #clock{ background:#dfb; }
  </style>
</head>
<body>
  <div id="boad">
    <svg id="clock" width="300px" height="300px" viewBox="0 0 300 300">
      <path id="hour" fill="#333" d="M148,80 l4,0 l3,100 l-10,0 l3,-100 Z"/>
      <path id="minute" fill="#333" d="M149,40 l2,0 l2,140 l-6,0 l2,-140 Z"/>
      <g id="second" stroke="#ca3" fill="#ca3">
        <line x1="150" y1="30" x2="150" y2="190" stroke-width="2"/>
        <circle cx="150" cy="150" r="6"/>
      </g>
      <script type="text/ecmascript">
        <![CDATA[
          var SVG = "http://www.w3.org/2000/svg";
          var rootobj = document.documentElement;
          var gg; var cx0=150; var cy0=150;
          for(var i = 0; i < 60; i++ ) {
            if(i%5==0){ 
              if(i==0){ moji=12;}else{moji=0.2*i};
              gg ="<polyline points='"+cx0+",42 "+cx0+",55' stroke='#666' fill='none' stroke-width='4' transform='rotate("+6*i+","+cx0+","+cy0+")'/>";
              gg+=  "<g font-size='28px' font-family='sans-serif' fill='#333' text-anchor='middle' dominant-baseline='middle' transform='rotate("+6*i+","+cx0+","+(cy0-0)+")'>";
              gg+=    "<text x='"+cx0+"' y='26' transform='rotate("+(-6*i)+","+cx0+",26)'>"+moji+"</text></g>";
            } else { 
              gg ="<polyline points='"+cx0+",42 "+cx0+",47' stroke='#888' fill='none' stroke-width='2' transform='rotate("+6*i+","+cx0+","+cy0+")'/>";
            }
            document.write(gg);
          }; // 文字盤表示終了 ----------------------

          var hour = new Hour();
          var minute = new Minute();
          var second = new Second();
          var last = 0;
          setInterval(function() {
            var now = new Date();
            var h = now.getHours();
            var m = now.getMinutes();
            var s = now.getSeconds();
            if (s != last) {
              hour.rotate(h, m, s);
              minute.rotate(m, s);
              second.rotate(s);
              last = s;
            }
          }, 100);
          
          //  ------------------------
          function Hour() {
            this.element = document.getElementById("hour");
            this.rotate = function(h, m, s) {
              var angle = h * 30 + m * 0.5 + s * 0.008;
              attribute = "rotate(" + angle + ", "+cx0+", "+cy0+")";
              this.element.setAttributeNS(null,"transform", attribute);
            };
          }; // Hour() ------------------------
          
          function Minute() {
            this.element = document.getElementById("minute");
            this.rotate = function(m, s) {
              var angle = m * 6 + s * 0.1;
              attribute = "rotate(" + angle + ", "+cx0+", "+cy0+")";
              this.element.setAttributeNS(null,"transform", attribute);
            };
          }; // Minute() ------------------------

          function Second() {
            this.element = document.getElementById("second");
            this.rotate = function(s) {
              var angle = s * 6;
              attribute = "rotate(" + angle + ", "+cx0+", "+cy0+")";
              this.element.setAttributeNS(null,"transform", attribute);
            };
          }; // Second() ------------------------
        ]]>
      </script>
    </svg>
  </div>
</body>
</html>

  【スミスチャート】 -SVG  参考
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" /> 
<title>SVG Smith Chart</title> 
</head> 
<body>
    <script>
      <!-- 
      var SMr0=150;                     // Smith円の半径(px)
      var SMcvV = 20;                   // Smith円の左右余白(px) 
      var SMcvG = 20;                   // Smith円の上下余白(px) 
      var SMcx0=SMr0+SMcvV; var SMcy0=SMr0+SMcvG;   // Smith円の中心位置
      var SMcvW = 2*(SMr0+SMcvV);       // SMcvの横幅(px) 
      var SMcvH = 2*(SMcy0+0);          // SMcvの縦幅(px)
      var SMtxtP=[
                   [0,0,-1,0],
                   [0.2,0.17,-0.92,0.38],
                   [0.5,0.33,-0.6,0.8],
                   [1,0.5,0,1],
                   [2,0.67,0.6,0.8],
                   [5,0.83,0.95,0.38],
                   [10,0.91,1.01,0.2]
                 ]
        document.open();
        document.write("<svg width='"+SMcvW+"' height='"+SMcvH+"' viewBox='0 0 "+SMcvW+" "+SMcvH+"' >\n");
        document.write("<rect x='0' y='0' width='"+SMcvW+"' height='"+SMcvH+"' stroke='black' stroke-width='1' fill='#dfb'/>\n");
        document.write("<line x1='"+SMcvV+"' y1='"+SMcy0+"' x2='"+(SMcvV+2*SMr0)+"' y2='"+SMcy0+"' stroke='#a60' stroke-width='1'/>\n");
        document.write("<g fill='none' stroke-width='1'>\n");
        for(j=0;j<SMtxtP.length;j++){            //等インピーダンス線を描く
          SMzz=SMtxtP[j][0]; //SMzx[j];
          SMcx=SMcx0+SMr0*SMzz/(1+SMzz);SMcy=SMcy0; SMr=SMr0/(1+SMzz); //等抵抗円半径を設定

          document.write("<circle cx='"+SMcx+"' cy='"+SMcy+"' r='"+SMr+"' fill='none' stroke='#a60' />\n");                                                   //等抵抗円を描く
          SMcx=SMcx0+SMr0; SMr=SMr0/SMzz; SMcy=SMcy0-SMr; //等インダクタンス弧半径を設定

          uv=1+SMzz*SMzz; u=(SMzz*SMzz-1)/uv;v=2*SMzz/uv;
          document.write("<path d='M "+(SMcx0+SMr0)+","+SMcy0+" A "+SMr+","+SMr+" 0 0,1 "+(SMcvV+SMr0+u*SMr0)+","+(SMcy0-v*SMr0)+"' stroke='#a60'/>\n");
          document.write("<path d='M "+(SMcx0+SMr0)+","+SMcy0+" A "+SMr+","+SMr+" 0 0,0 "+(SMcvV+SMr0+u*SMr0)+","+(SMcy0+v*SMr0)+"' stroke='#a60'/>\n");
        }
        document.write("</g>");
        document.write("<g font-size='12' text-anchor='middle'>\n");
        document.write("<text x='45' y='14'>Smith chart</text>");
        document.write("<text x='"+(SMcvW-40)+"' y='14'>by くらげ</text>");
          document.write("<text x='"+(2.04*SMr0+SMcvV)+"' y='"+(SMcy0+4)+"'>∞</text>");
        for(j=0;j<SMtxtP.length;j++){            // 抵抗目盛を描く
          document.write("<text x='"+(2*SMtxtP[j][1]*SMr0+SMcvV)+"' y='"+(SMcy0+14)+"'>"+SMtxtP[j][0]+"</text>");
          if (j!=0){
            document.write("<text x='"+(SMtxtP[j][2]*SMr0+SMcx0)+"' y='"+(SMcy0-SMtxtP[j][3]*SMr0-4)+"'>"+SMtxtP[j][0]+"j</text>");
            document.write("<text x='"+(SMtxtP[j][2]*SMr0+SMcx0)+"' y='"+(SMcy0+SMtxtP[j][3]*SMr0+14)+"'>-"+SMtxtP[j][0]+"j</text>");
          }  
        }
        document.write("</g>");
        document.write("</svg>");
        document.close();
      //-->
    </script>
</body>
</html>

  【 JavaScript や Css を組み込んだ -SVG 1 】  参考
<svg width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <script type="text/javascript">
    // <![CDATA[  https://developer.mozilla.org/ja/docs/Web/SVG/Element/script
    function change(evt) {  // 楕円 click 時の対応
      var target = evt.target;
      var radius = target.getAttribute("r");
      if (radius == 10) {
        radius = 20;
      } else {
        radius = 10;
      }
      target.setAttribute("r",radius);
   }
   // ]]>
  </script>
    
  <desc>Example anim01 - demonstrate animation elements</desc>
  <g transform="translate(10,10)" >
    <!-- The following illustrates the use of the 'set', 'animateMotion',
         'animate' and 'animateTransform' elements. The 'text' element 
         below starts off hidden (i.e., invisible). At 0 seconds, it:
           * becomes visible
           * continuously moves diagonally across the viewport
           * changes color from blue to red
           * rotates from -550 to zero degrees
           * scales by a factor of two. -->
    <text id="TextElement" x="-10" y="0"
          font-family="Verdana" font-size="2.4" visibility="hidden"  > 
        Click me !!
      <set attributeName="visibility" attributeType="CSS" to="visible"
           begin="0s" dur="2s" fill="freeze" />
      <animateMotion path="M 10 10 L 47 42" 
           begin="0s" dur="2s" fill="freeze" />
      <animate attributeName="fill" attributeType="CSS"
           from="rgba(0,0,255,0.2)" to="rgba(248,0,128,1)"
           begin="0s" dur="2s" fill="freeze" />
      <animateTransform attributeName="transform" attributeType="XML"
           type="rotate" from="-550" to="0"
           begin="0s" dur="2s" fill="freeze" />
      <animateTransform attributeName="transform" attributeType="XML"
           type="scale" from="0.5" to="2" additive="sum"
           begin="0s" dur="2s" fill="freeze" />
    </text>
  </g>
  
  <g transform="translate(50,50)"> <!-- クリックで変形するぷあぷあ楕円  -->
    <circle class="ellipse ellipse1"  cx="0" cy="0" r="20" fill="#aea" fill-opacity="0.5" onclick="change(evt)">
    <animateTransform
       attributeName="transform"
       attributeType="XML"
       type="scale" dur="6s"
       repeatCount="indefinite"
       values="1 1.5; 2.5 0.7; 1 1.5" />
    </circle>
  </g>
</svg>

  【 JavaScript や Css を組み込んだ -SVG 2 】  参考
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" id="loading_svg" onload=' init(); '>
  <script type="text/javascript">
    // <![CDATA[  
    function init(){  
      var now = new Date();
      var h = now.getHours(), m = now.getMinutes(), s = now.getSeconds();

       var line0 = document.getElementsByTagName("line")[0]; 
       var txt0 =  "rotate( " + (h * 30 + m * 0.5 +  s / 120) + ", 100, 100)";
       line0.setAttribute( "transform", txt0 );
      
       var line1 = document.getElementsByTagName("line")[1]; 
       var txt1 =  "rotate( " + (m * 6 + 0.1 * s) + ", 100, 100)";
       line1.setAttribute( "transform", txt1 );
       
       var line2 = document.getElementsByTagName("line")[2];  
       var txt2 =  "rotate( " + s * 6 + ", 100, 100)";
       line2.setAttribute( "transform", txt2 );
    }
   // ]]>
  </script>
  
    <circle id="clockBase" cx="100" cy="100" r="100" fill="skyblue"/>
    <circle id="dot" cx="100" cy="10" r="6" fill="#888"/>
    <circle id="dot" cx="145" cy="22.1" r="2" fill="#444"/>
    <circle id="dot" cx="177.9" cy="55" r="2" fill="#666"/>
    <circle id="dot" cx="190" cy="100" r="4" fill="#444"/>
    <circle id="dot" cx="177.9" cy="145" r="2" fill="#444"/>
    <circle id="dot" cx="145" cy="177.9" r="2" fill="#444"/>
    <circle id="dot" cx="100" cy="190" r="4" fill="#666"/>
    <circle id="dot" cx="55" cy="177.9" r="2" fill="#444"/>
    <circle id="dot" cx="22.1" cy="145" r="2" fill="#444"/>
    <circle id="dot" cx="10" cy="100" r="4" fill="#666"/>
    <circle id="dot" cx="22.1" cy="55" r="2" fill="#444"/>
    <circle id="dot" cx="55" cy="22.1" r="2" fill="#444"/>
    
    <g stroke-linecap="round">
        <!--時針-->
        <line x1="100" y1="50" x2="100" y2="90" stroke="red" stroke-width="7">
            <animateTransform attributeName="transform" type="rotate" begin="0s" dur="12h" additive="sum" from="0,100,100" to="360,100,100" repeatCount="indefinite" calcMode="linear"/>
        </line>
        <!--分針-->
        <line x1="100" y1="30" x2="100" y2="95" stroke="yellow" stroke-width="5" transform="rotate(45, 100, 100)">
            <animateTransform attributeName="transform" type="rotate" begin="0s" dur="1h" additive="sum" from="0,100,100" to="360,100,100" repeatCount="indefinite" calcMode="linear"/>
        </line>
        <!--秒針-->
        <line x1="100" y1="10" x2="100" y2="100" stroke="blue" stroke-width="3" transform="rotate(45, 100, 100)">
            <animateTransform attributeName="transform" type="rotate" begin="0s" dur="1min" additive="sum" from="0,100,100" to="360,100,100" repeatCount="indefinite" calcMode="linear"/>
        </line>
    </g>
</svg>

■ SVG(Scalable Vector Graphics)

使い方
リファレンス
アプリGraphicsJS
DOM
アニメーション
その他

■ 関連サイト

可視(グラフ)化
ブラウザで図形を描く
QRコード作成
その他