前回はC# WindowsFormsでジグソーパズルを作りましたが、今回はJavaScriptでジグソーパズルを作ります。

HTML部分

まずHTML部分を示します。ピースの形状の関係によって端に20ピクセルの隙間ができてしまうので、ボタンを20ピクセル右に寄せています。

JavaScript部分

主な定数とグローバル変数を示します。ピースのサイズは80ピクセルとします。ピースのサイズとは赤い枠で囲まれている部分です。そのため画像のサイズは120ピクセルになります。

Pieceクラスの定義

ピースを描画したり位置情報を管理するためのPieceクラスを定義します。IsClick関数はクリックされた座標が上記の図の赤い矩形内かどうかを返すためのものです。

ピースの生成

ページが読み込まれたら猫の画像を読み込んで、これを元にピースを生成します。生成されたPieceオブジェクトは配列に格納します。ちなみに管理人は鳩を自称していますが、本当は猫好きです。

パズルの元の画像を読み込む処理を示します。image.src = ‘./cat.png’;を実行してから画像が読み込まれるまで時間がかかるのでPromiseオブジェクトを使って完了するまで待機できるようにしています。

ピースを生成する処理を示します。別のcanvasとコンテキストを生成してピースの形にパスを生成します。ctx.clip();を実行したあとdrawImage関数を実行すればピースの内部だけに画像を描画することができます。あとはこれをbase64に変換し、これをもとに新しいピースを生成します。

渡されたbase64から新しいピースを生成する処理を示します。これもimage.src = base64;が実行されてから読み込みが完了するまで時間がかかるのでPromiseオブジェクトを生成して待機できるようにしています。

ピースの描画

drawAll関数はすべてのピースを描画します。描画の順番によっては現在移動中のピースが他のピースの後ろに隠れてしまうので、この場合だけ最後に再描画しています。

ピースの移動

ピースをドラッグ&ドロップで移動させる処理を示します。

マウスボタンが押下されたらどのピースがクリックされたかを調べて該当するものが存在する場合はmovingPieceに格納します。そしてもとの座標も保存しておきます。該当するピースが存在しない場合はなにもしません。

movingPieceに値が格納されている状態でマウスが移動したときの処理を示します。

マウスポインタの位置に移動中のピースの中央部分が描画されるようにしています。またボタンを押したままマウスポインタをウィンドウの外に移動させるとピースを見えない位置に移動できてしまうので、そうならないように対策をしています。

マウスボタンを離したときの処理を示します。

ピースが自動的に組み合わさるように完成したパズルが描画される部分へはpieceSizeの整数倍の座標にしか配置されないようにしています。またすでにピースがある部分には置けないようにしています。それ以外の場所であれば自由に配置できるようにしています。

シャッフルと完成の判定

ピースをシャッフルする処理を示します。piecesの中身を変数arrのなかへコピーします。そしてランダムにひとつずつ取り出して新しいX座標とY座標を割り当てます。またかかった時間を計測するためにグローバル変数timeを0で初期化して1秒ごとにカウントアップしていきます。

完成したかどうかをチェックする処理を示します。Piece.Check関数がすべてtrueを返せばすべてのピースがあるべき位置に配置されていることになります。この場合はタイマーを停止させます。