JavaScript入門[HTML5編]ドラッグ中の画像の変更

  1. HOME
  2. JavaScript入門[HTML5編]
  3. ドラッグ中の画像の変更

HTML5では、ドラッグ中の画像を変更することができます。 このページではその方法を見ていくことにしましょう。

ドラッグ中の画像を変更するサンプルスクリプト

ドラッグ中の画像を指定するには、setDragImage()を使います。 以下のように記述します。

event.dataTransfer.setDragImage( DOM要素 , X座標 , Y座標 )
ドラッグ中に、第1引数で指定したDOM要素のキャプチャ画像が表示されます。
第1引数がimgタグの場合、src属性に指定した画像を表示します。
第2引数は画像を表示するX座標、第3引数はY座標を指定します。
dragstartイベント内で指定します。

では実際に移動中の画像を変更してみることにしましょう。 以下のサンプルでは、赤の四角だけドラッグ可能です。 そのドラッグ中に、どのように表示されるか確かめて見てください。

<サンプル>赤の四角をドラッグして下のエリアに移動してみてください。

赤四角をドラッグすると、上のエリア全体のキャプチャ画像が表示されると思います。 このサンプルのスクリプトは以下の通りです。

<div id="dragarea" class="dd">
  <div id="red" draggable="true"></div>
  <div id="green"></div>
</div>
<div id="droparea" class="dd"></div>

<style type="text/css">
div.dd{ width:100%; height:100px }
div#dragarea{ background-color:#80ffff }
div#droparea{ background-color:#ffff80 }
div.dd div{ width:100px; height:100px; float:left }
div#red { background-color:red }
div#green { background-color:green }
</style>

<script>

var obj1 = document.getElementById("red");
var obj2 = document.getElementById("droparea");

//ドラッグイメージに使うDOM要素を取得
var dimg = document.getElementById("dragarea");


obj1.addEventListener("dragstart", function(evt){
  evt.dataTransfer.setData("text/plain",evt.target.id);

  //ドラッグイメージの設定
  evt.dataTransfer.setDragImage(dimg,100,50);

  evt.stopPropagation();
},false);


obj2.addEventListener("drop", function(evt){
  var id=evt.dataTransfer.getData("text/plain");
  var obj3 = document.getElementById(id);
  if ( obj3 ){ obj2.appendChild( obj3 ) }
  evt.preventDefault();
},false);

obj2.addEventListener( "dragenter" , function(evt){
  evt.preventDefault();
}, false );
obj2.addEventListener( "dragover" , function(evt){
  evt.preventDefault();
}, false );
</script>

スクリプトの解説

では、上記のスクリプトを詳しく見ていきましょう。

HTML部分

<div id="dragarea" class="dd">
  <div id="red" draggable="true"></div>
  <div id="green"></div>
</div>
<div id="droparea" class="dd"></div>

まずはドラッグ要素を表示する上の列と、ドロップされる下の列を構成するdivタグを設けました。 それぞれid名を「dragarea」,「droparea」とし、クラス名「dd」も付けています。

また上の列の中に、2色の正方形を表示させるため、divタグを2つ書き加えています。 それぞれのid名は「red」,「green」です。 赤の正方形はドラッグ可能にするため、draggable属性を記述しています。

CSS部分

<style type="text/css">
div.dd{ width:100%; height:100px }
div#dragarea{ background-color:#80ffff }
div#droparea{ background-color:#ffff80 }
div.dd div{ width:100px; height:100px; float:left }
div#red { background-color:red }
div#green { background-color:green }
</style>

スタイルシート部分の説明を簡単にしておきます。 1行目は、クラス名「dd」が付いたdivタグの横幅を100%,高さを100pxにしています。

2行目と3行目は、背景色の指定です。 id名「dragarea」の付いたdivタグは薄い青に、 id名「droparea」の付いたdivタグは薄い黄色に指定しました。

4行目は、クラス名「dd」のついたdivタグの中にあるdivタグの縦横幅を100px、 左寄せして右に他の要素を回り込ませるようにしています。

5,6行目も背景色の指定です。クラス名「red」の付いたdivタグは赤に、 クラス名「green」の付いたdivタグは緑にしています。

DOM要素の取得

var obj1 = document.getElementById("red");
var obj2 = document.getElementById("droparea");
var dimg = document.getElementById("dragarea");

続いてスクリプトの内部を見ていきましょう。 最初はgetElementById()を使って各要素を掴み、変数に格納しています。 ドラッグする赤正方形は変数obj1に、ドロップされる列は変数obj2に格納します。

変数dimgには、id名「dragarea」が付いたdivタグを格納しています。 このDOM要素のキャプチャ画像を、ドラッグ中に表示しようと思います。

dragstartイベントの追加

obj1.addEventListener("dragstart", function(evt){
  evt.dataTransfer.setData("text/plain",evt.target.id);

  evt.dataTransfer.setDragImage(dimg,100,50);

  evt.stopPropagation();
},false);

赤の正方形に、dragstartイベントをaddEventListener()で追加しています。 イベント内で、ドラッグ中の要素のid名をdataTransferに渡しています。

続いて、ドラッグ中の画像をsetDragImage()で指定しています。 表示するのは変数dimgに格納したDOM要素のキャプチャ画像です。 その要素の座標(100,50)にマウスカーソルが来るように表示しています。 ちょうど赤と緑の正方形の中間になります。

stopPropagation()で、イベントの予期せぬ伝播を防ぎます。

dropイベントの追加

obj2.addEventListener("drop", function(evt){
  var id=evt.dataTransfer.getData("text/plain");
  var obj3 = document.getElementById(id);
  if ( obj3 ){ obj2.appendChild( obj3 ) }
  evt.preventDefault();
},false);

下側の列を構成するdivタグに、dropイベントを追加します。 イベント内で、dataTransferからドラッグ要素のid名を受け取り、 appendChild()で移動するのはこれまで通りです。 ブラウザのデフォルト動作も抑制しておきます。

2つのイベントでデフォルトの動作を抑制

obj2.addEventListener( "dragenter" , function(evt){
  evt.preventDefault();
}, false );
obj2.addEventListener( "dragover" , function(evt){
  evt.preventDefault();
}, false );

dragenterイベントとdragoverイベントでブラウザのデフォルト動作を抑制するのもこれまで通りです。