JavaScriptで図形をドラッグ!7ステップで完璧に理解

JavaScriptで作成された図形のドラッグ操作JS
この記事は約12分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事を読むことで、JavaScriptを使って図形をドラッグする方法が分かるようになります。

初心者でも理解できるよう、基本から応用まで段階的に解説しています。

サンプルコードも用意しているので、ぜひ実際に試してみてください。

●JavaScriptで図形を描く基本

まずは、JavaScriptで図形を描く方法を学びましょう。

○HTMLとCanvas要素の準備

HTMLファイルにCanvas要素を追加し、JavaScriptで図形を描画するための基本的な準備を行います。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>図形をドラッグする</title>
</head>
<body>
  <canvas id="myCanvas" width="800" height="600"></canvas>
  <script src="main.js"></script>
</body>
</html>

○図形を描くコード

次に、JavaScriptファイル(main.js)を作成し、次のコードを記述して、Canvas上に図形を描画します。

// Canvas要素を取得
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// 図形を描画する関数
function drawShape(x, y, width, height) {
  ctx.beginPath();
  ctx.rect(x, y, width, height);
  ctx.fillStyle = 'blue';
  ctx.fill();
  ctx.closePath();
}

// 図形を描画
drawShape(50, 50, 100, 100);

このコードでは、drawShape関数を使って、指定した座標に指定したサイズの四角形を描画しています。

この例では、(50, 50)の座標に100×100ピクセルの青色の四角形を描画しています。

●ドラッグ操作の実装

図形をドラッグできるようにするため、マウスイベントを検出し、図形のドラッグ操作を実装します。

○マウスイベントの検出

下記のコードをmain.jsに追加して、マウスのイベントを検出します。

// マウスイベントのリスナーを追加
canvas.addEventListener('mousedown', onMouseDown);
canvas.addEventListener('mousemove', onMouseMove);
canvas.addEventListener('mouseup', onMouseUp);

// マウスイベントのコールバック関数
function onMouseDown(e) { /* ここに処理を書く */ }
function onMouseMove(e) { /* ここに処理を書く */ }
function onMouseUp(e) { /* ここに処理を書く */ }

○図形のドラッグ操作

図形をドラッグできるようにするため、マウスイベントの検出で設定したコールバック関数に処理を追加します。

次のコードをmain.jsに追加してください。

// 図形の位置情報
let shape = { x: 50, y: 50, width: 100, height: 100 };

// ドラッグ中の状態を保持する変数
let isDragging = false;

// マウスダウンイベントの処理
function onMouseDown(e) {
  const mouseX = e.clientX - canvas.offsetLeft;
  const mouseY = e.clientY - canvas.offsetTop;

  if (mouseX >= shape.x && mouseX <= shape.x + shape.width &&
      mouseY >= shape.y && mouseY <= shape.y + shape.height) {
    isDragging = true;
  }
}

// マウスムーブイベントの処理
function onMouseMove(e) {
  if (!isDragging) return;

  const mouseX = e.clientX - canvas.offsetLeft;
  const mouseY = e.clientY - canvas.offsetTop;

  const dx = mouseX - shape.x;
  const dy = mouseY - shape.y;

  shape.x += dx;
  shape.y += dy;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawShape(shape.x, shape.y, shape.width, shape.height);
}

// マウスアップイベントの処理
function onMouseUp(e) {
  isDragging = false;
}

このコードでは、onMouseDown関数でマウスが図形の範囲内でクリックされたかどうかを判定し、ドラッグ中の状態を管理するisDragging変数にtrueを代入しています。

onMouseMove関数では、ドラッグ中であれば図形の位置を更新し、再描画しています。

最後に、onMouseUp関数でドラッグが終了した際にisDragging変数をfalseに戻しています。

●サンプルコード

○サンプルコード1:基本的な図形のドラッグ

これまでの手順で実装したコードが、基本的な図形のドラッグを実現するサンプルコードです。

図形のドラッグ操作を確認できます。

○サンプルコード2:複数の図形のドラッグ

複数の図形をドラッグできるようにするためのサンプルコードを紹介します。

このコードでは、shapes配列に複数の図形の情報を格納し、それぞれに対してドラッグ操作を実装しています。

// 複数の図形を保持する配列
let shapes = [
  { x: 50, y: 50, width: 100, height: 100 },
  { x: 200, y: 100, width: 80, height: 120 },
];

// 図形を描画する関数をアップデート
function drawShapes() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  shapes.forEach((shape) => {
    ctx.beginPath();
    ctx.rect(shape.x, shape.y, shape.width, shape.height);
    ctx.fillStyle = 'blue';
    ctx.fill();
    ctx.closePath();
  });
}

// マウスダウンイベントの処理をアップデート
function onMouseDown(e) {
  const mouseX = e.clientX - canvas.offsetLeft;
  const mouseY = e.clientY - canvas.offsetTop;

  shapes.forEach((shape) => {
    if (
      mouseX >= shape.x &&
      mouseX <= shape.x + shape.width &&
      mouseY >= shape.y &&
      mouseY <= shape.y + shape.height
    ) {
      isDragging = true;
      shape.dragging = true;
    }
  });
}

// マウスムーブイベントの処理をアップデート
function onMouseMove(e) {
  if (!isDragging) return;

  const mouseX = e.clientX - canvas.offsetLeft;
  const mouseY = e.clientY - canvas.offsetTop;

  shapes.forEach((shape) => {
    if (shape.dragging) {
      const dx = mouseX - shape.x;
      const dy = mouseY - shape.y;

      shape.x += dx;
      shape.y += dy;
    }
  });

  drawShapes();
}

// マウスアップイベントの処理をアップデート
function onMouseUp(e) {
  isDragging = false;
  shapes.forEach((shape) => {
    shape.dragging = false;
  });
}

// 初期描画
drawShapes();

このサンプルコードでは、複数の図形が描画されており、それぞれを個別にドラッグできるようになっています。

各図形に対して、マウスダウンイベント、マウスムーブイベント、マウスアップイベントを適用し、ドラッグ操作を実現しています。

●応用例とサンプルコード

○応用例1:ドラッグで図形を移動

この応用例では、ドラッグ操作を用いて図形を移動させる方法を説明します。

サンプルコード1およびサンプルコード2で実現した基本的な図形のドラッグと複数の図形のドラッグは、この応用例で示したドラッグで図形を移動する機能に相当します。

 -サンプルコード3:ドラッグで図形を移動させる

サンプルコード3では、ドラッグで図形を移動させる方法を実装しています。

この例では、図形のドラッグ操作を実現するために、マウスダウンイベント、マウスムーブイベント、およびマウスアップイベントを使用しています。

// サンプルコード3
let isDragging = false;

canvas.addEventListener('mousedown', onMouseDown);
canvas.addEventListener('mousemove', onMouseMove);
canvas.addEventListener('mouseup', onMouseUp);

function onMouseDown(e) {
  if (isPointInsideRect(e.clientX, e.clientY, rect)) {
    isDragging = true;
  }
}

function onMouseMove(e) {
  if (!isDragging) return;

  const dx = e.movementX;
  const dy = e.movementY;

  rect.x += dx;
  rect.y += dy;

  drawRect();
}

function onMouseUp(e) {
  isDragging = false;
}

このコードでは、マウスダウンイベントが発生した際に、isDragging変数をtrueに設定して図形のドラッグ操作を開始します。

マウスムーブイベントが発生すると、図形の位置を更新し、再描画します。

最後に、マウスアップイベントが発生した際に、isDragging変数をfalseに設定してドラッグ操作を終了します。

○応用例2:ドラッグで図形のサイズ変更

 -サンプルコード4:ドラッグで図形のサイズを変更する

サンプルコード4では、ドラッグ操作を使用して図形のサイズを変更する方法を実装しています。

この例では、図形の端をドラッグしてサイズを変更するために、マウスダウンイベント、マウスムーブイベント、およびマウスアップイベントを使用しています。

// サンプルコード4
let isResizing = false;

canvas.addEventListener('mousedown', onResizeStart);
canvas.addEventListener('mousemove', onResizeMove);
canvas.addEventListener('mouseup', onResizeEnd);

function onResizeStart(e) {
  if (isPointOnRectBorder(e.clientX, e.clientY, rect)) {
    isResizing = true;
  }
}

function onResizeMove(e) {
  if (!isResizing) return;

  const dx = e.movementX;
  const dy = e.movementY;

  rect.width += dx;
  rect.height += dy;

  drawRect();
}

function onResizeEnd(e) {
  isResizing = false;
}

このコードでは、マウスダウンイベントが発生した際に、図形の端をクリックしているかを判定し、isResizing変数をtrueに設定してサイズ変更操作を開始します。

マウスムーブイベントが発生すると、図形のサイズを更新し、再描画します。

最後に、マウスアップイベントが発生した際に、isResizing変数をfalseに設定してサイズ変更操作を終了します。

●注意点と対処法

ドラッグ操作を実装する際には、いくつかの注意点があります。

主な注意点とその対処法を紹介します。

ドラッグ操作が他の要素に影響を与える場合

ドラッグ操作中にマウスカーソルが他の要素に重なると、意図しない動作が発生することがあります。

これを防ぐために、event.preventDefault()を使用して、デフォルトのイベント動作をキャンセルします。

マウスイベントがキャンバス外で発生する場合

マウスイベントがキャンバス外で発生した場合、正常なドラッグ操作ができなくなることがあります。

対処法として、ドラッグ操作中にマウスがキャンバス外に出た場合でも、正常に動作するようにイベントリスナをwindowオブジェクトに設定します。

●カスタマイズ方法

ドラッグ操作を実装したプログラムは、さまざまなカスタマイズが可能です。

例えば、下記のようなカスタマイズが考えられます。

図形の種類の追加

円や多角形など、さまざまな図形を追加してドラッグ操作ができるようにカスタマイズできます。

クリック時の図形生成

マウスクリック時に新しい図形を生成し、その場でドラッグ操作ができるようにカスタマイズできます。

図形の連結

複数の図形を連結し、一度にドラッグ操作ができるようにカスタマイズできます。

ズーム機能の追加

図形を拡大・縮小できるように、ズーム機能を追加することができます。

まとめ

この記事では、JavaScriptを使用して図形を描画し、ドラッグ操作を実装する方法を紹介しました。

サンプルコードを参考に、自分自身でカスタマイズし、独自のドラッグ操作を実装できるようになることが期待されます。

また、注意点と対処法を押さえておくことで、さらなる問題にも対応できるでしょう。

これを機に、JavaScriptを使った図形操作に挑戦してみてください。