【JavaScript】 Path2D:Canvasのパスを個別登録しておいて使いまわす
更新日:2023/01/30
JavaScriptのCanvasAPIで描画をするとき、頻繁に使用するパスはPath2Dを使用すると何度でも使いまわすことができます。
アニメーションなどを表現するなら、とても便利な機能です。
そこで今回は、Path2Dについてお伝えします。
Path2Dの使い方
Path2Dオブジェクトの取得
Path2Dオブジェクトは、Path2Dのコンストラクタから取得します。
const path = new Path2D();
Path2Dオブジェクトのコピー
既存のPath2Dオブジェクトを、Path2Dのコンストラクタに引数として与えることでコピーすることができます。
const path = new Path2D();
・・・pathを操作する
const newPath = = new Path2D( path );
Path2Dオブジェクトにパスを登録
Path2Dオブジェクトは、次のメソッドでパスを登録できます。
使用方法は、同名のCanvasAPIメソッドと同じです。
Path2D.closePath()
Path2D.moveTo()
Path2D.lineTo()
Path2D.bezierCurveTo()
Path2D.quadraticCurveTo()
Path2D.arc()
Path2D.arcTo()
Path2D.ellipse()
Path2D.rect()
Path2Dオブジェクトを描画
Path2Dオブジェクトに登録したパスの描画は、CanvasAPIのコンテキストのfill()またはstroke()メソッドに引数として渡します。
const context = canvas.getContext('2d');
const path = new Path2D();
path.moveTo( 10 , 10 );
path.lineTo( 100 , 10 );
path.lineTo( 100 , 100 );
path.closePath();
context.stroke( path );
Path2Dオブジェクトを別のPath2Dオブジェクトに追加
addPath()メソッドを使用することで、Path2Dオブジェクトを別のPath2Dオブジェクトに追加することができます。
const context = canvas.getContext('2d');
const path = new Path2D();
path.rect( 10 , 10 , 50 , 50);
const path2 = new Path2D();
path2.rect( 30 , 30 , 50 , 50);
path.addPath( path2);
context.stroke( path );
追加するPath2Dオブジェクトは、それ自体で完結している必要があります。
次の例は、Path2Dオブジェクトを描画のコードをPath2Dオブジェクトに分割しています。
const path = new Path2D();
path.moveTo( 10 , 10 );
path.lineTo( 100 , 10 );
const path2 = new Path2D();
path2.lineTo( 100 , 100 );
path2.closePath();
path.addPath( path2);
context.stroke( path );
三角形が描画されるのを期待していましたが、描画されませんでした。
lineTo()メソッドは、moveTo()メソッドで始点を設定する必要があります。
上の例ではpath2に対して、moveTo()メソッドを使用していないためlineTo()で直線を登録できていません。
そのためpathにpath2を追加しても、期待通りの結果とならなかったのです。
Path2Dの具体的な使用例
異なる位置・色で描画する
fillStyleに色を、translateを使用して移動をおこないます。
const color = ["red","blue","green","pink"];
const path = new Path2D();
path.moveTo( 10 , 10 );
path.lineTo( 100 , 10 );
path.lineTo( 100 , 100 );
path.closePath();
color.forEach( (e,i)=>{
context.save();
context.fillStyle = e;
context.translate( i * 100 , 0 );
context.fill( path );
context.restore();
});
回転と拡大をおこなう
次はPath2Dを使用して、同じ図形の拡大と回転をおこなってみます。
まずはデモを見てください。
「実行/停止」を押すと、実際にJavaScriptで動作します。
コード
HTML
<div id="canvas_wrap">
<canvas id="canvas" height="350" width="600"></canvas>
</div>
CSS
#canvas_wrap{
padding:0;
margin:0;
border:1px solid #000;
}
#canvas{
width:100%;
}
JavaScript
#canvas_wrap{
padding:0;
margin:0;
border:1px solid #000;
}
#canvas{
width:100%;
}
window.addEventListener( "DOMContentLoaded" , ()=> {
const canvas = document.getElementById( "canvas" );
const context = canvas.getContext( "2d" );
const [ canvasWidth , canvasHeight ] = [ canvas.width , canvas.height ];
const [ canvasWidthHalf , canvasHeightHalf ] = [ canvasWidth / 2 , canvasHeight / 2];
context.fillStyle = "pink";
context.strokeStyle = "blue";
context.lineWidth = 3;
// キャンバスの中心を原点(0,0)にセット
context.translate( canvasWidthHalf , canvasHeightHalf );
context.save();
// Path2Dオブジェクト作成(ハート形)
const path = new Path2D();
path.moveTo( 0 , 43);
path.quadraticCurveTo(70 , 3, 70 , -37);
path.bezierCurveTo(70 , -77 , 20 , -77, 0 , -37);
path.bezierCurveTo(-20 , -77, -70 , -77, -70 , -37);
path.quadraticCurveTo(-70 , 3 , 0 , 43);
let sc = 0.1, rd = 0, dir = 1;
let x = -canvasWidthHalf , xStep = canvasWidthHalf / 20;
let y = -canvasHeightHalf , yStep = canvasHeightHalf / 20;
// インターバルセット
setInterval(
()=>{
// キャンバスクリア
context.clearRect( -canvasWidthHalf , -canvasHeightHalf , canvasWidth , canvasHeight);
context.save();
// コンテキストで描画
context.beginPath();
context.moveTo( x , -canvasHeight);
context.lineTo( x , canvasHeight );
context.moveTo( -canvasWidthHalf , y);
context.lineTo( canvasWidthHalf , y );
context.stroke();
// キャンバス座標の拡大と回転
context.scale(sc,sc);
context.rotate( dir * rd * Math.PI/180);
// Path2Dオブジェクトを描画
context.fill(path);
context.restore();
// 各変数を更新
[ sc ,dir] = sc > 5.0 ? [ 0 , dir * -1] : [ sc + 0.1 , dir];
rd = ( rd > 350 ) ? 0 : rd + 10;
x = ( x > canvasWidthHalf - xStep ) ? -canvasWidthHalf : x + xStep;
y = ( y > canvasHeightHalf - yStep ) ? -canvasHeightHalf : y + yStep;
},50
);
});
最初に後ろの青いラインを、コンテキストで直接描画しています。
その後座標系の拡大と回転を行った後、pathを元に描画をおこなっています。
更新日:2023/01/30
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。