Help us understand the problem. What is going on with this article?

Javascript でドラック&ドロップを実装 (ライブラリ使わない)

More than 1 year has passed since last update.

はじめに

Javascript でドラックアンドドロップを実装するよー
全体の流れは以下です。
1. 移動させたい要素のpositionをabsoluteにする
2. マウスが移動するイベントを受け取り、移動させたい要素の(x,y)をマウスポインタの(x,y)と同じにする
3. マウスが離れたとき、ある矩形にマウスポインタが入ってるかどうか判定。

実装

クリックに対応させる

まずはマウスがクリックされたイベントを受け取りましょう。
簡単なhtml を書いてimgタグで画像を表示させます。
次にjavascriptでマウスクリックに対応させます。
htmlの要素がマウスクリックされると、onmousedownイベントが呼ばれます。
javascriptでonmousedownイベントをフックして、コンソールに文字列を表示させます。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>balltest</title>
</head>
<body>
  <div id="app">
    <img src="ball.png" id="ball" width="80px">
  </div>
  <script>
    var ball = document.getElementById("ball");
    ball.onmousedown = function(event){
      console.log("タップされたよ!");
    }
  </script>
</body>
</html>

画像がマウスの位置についてくる

次に、マウスが移動するイベントをフックします。
画像の位置を自由自在に操れるようにしたいので、positionをabsoluteにしておきます。

ball.style.position = "absolute";

ondragstartイベントはドラッグ操作を開始したときに呼ばれます。
ですが今回はmousemoveイベントを使って実装するのはこれは不要です。

ball.ondragstart = function(event){
  return false;
}

マウスが移動したときに、それと同じ位置に画像を配置します。
マウスポインタの(x,y)と、画像の(x,y)が同期するイメージです。
clientX は、ブラウザ画面の左端からの距離を取得します。
clientY はブラウザ画面の上端からの距離を取得します。
offsetWidth, offsetHeight では要素のサイズが取得できます。
これらの組み合わせて、マウスポインタの位置と画像の位置を同じにしましょう。
マウスポインタがすこしでも移動したとき(mousemoveイベント)にこれを登録します。

ball.onmousedown = function(event){
  document.addEventListener("mousemove",onMouseMove);
}
var onMouseMove = function(event){
  var x = event.clientX;
  var y = event.clientY;
  var width = ball.offsetWidth;
  var height = ball.offsetHeight;
  ball.style.top = (y-height/2) + "px";
  ball.style.left = (x-width/2) + "px";
}

ドロップで画像を削除

ある矩形内でマウスが離されたときに画像を削除する処理を追加します。
今回はいらすと屋からゴミ箱の画像を借りてきました。
マウスが離された時(onmouseupイベントが呼ばれた時)にやるべきことは2つです。

  • 画像がマウスポインタにひっついてくるイベントを解除
  • マウスポインタがゴミ箱の矩形内に存在するか判定する。trueならばボールを削除、falseならば何もしない
<img src="gomibako.png" id="gomibako" width="150px"><br>

(省略)

ball.onmouseup = function(event){
  var x = event.clientX;
  var y = event.clientY;
  var width = ball.offsetWidth;
  var height = ball.offsetHeight;
  var gomibakoRect = gomibako.getBoundingClientRect();
  if((x>=gomibakoRect.left && x<=(gomibakoRect.left+gomibakoRect.width)) && (y>=gomibakoRect.top && y<=(gomibakoRect.top+gomibakoRect.height))){
    var app = document.getElementById("app");
    app.removeChild(ball);
  }
  document.removeEventListener("mousemove",onMouseMove);
}

以上、こんな感じでドラックアンドドロップが実装できました!

まとめ

javascriptでドラックアンドドロップを実装するには・・・

  • 要素のpositionをabsolute にする
  • mousemove、mousedown、mousemoveイベントハンドラを上手に使う

ソースコードはこちらにおいておいておきます。
デモはこちらから試せます。
以上です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away