Drag and Drop 0.1

ドラッグアンドドロップの実験をしてみました。img 要素は元々ドラッグできるとのことなので、 それを試してみました。JavaScript がなくてもドラッグはできますが、ドロップすると元に戻ります。

JavaScript の処理の中で、ドロップした時点の座標に img 要素を移動するようにしました。 また、ドロップ時に img 要素の z-index も変更し、手前に来るようにしました。

img 要素には 182 × 110 ピクセルの png ファイルを使用しました。サイズが大きいと、 ドラッグ時に縮小されてしまい、座標の計算が合いません。

実行結果

ソース


dragndrop01.html

JavaScript のソースファイルを指定します。
<script type="text/javascript" src="js/dragondrop01/dragndrop01.js"></script>

この HTML で使う style を指定します。

<style>
#table {
    width: 97%;
    height: 300px;
    padding: 10px;
	background-color: tan;
	position: relative;
}
#card1, #card2 {
	position: absolute;
}
#card1 {
	z-index: 1;
	left: 10px;
	top: 10px;
}
#card2 {
	z-index: 2;
	left: 20px;
	top: 20px;
}
</style>
カード2枚(img 要素)とテーブル(div 要素)。img 要素は draggable="true" を指定しなくてもドラッグできます。
<h2>実行結果</h2>
<div id="table">
<img src="img/card1.png" id="card1">
<img src="img/card2.png" id="card2">
</div>

dragndrop01.js

ドラッグアンドドロップの処理を指定します。

window.onload = function() {
    var offsetX = 0;
    var offsetY = 0;
    var table = document.getElementById('table');
    var tableX = table.getBoundingClientRect().left;
    var tableY = table.getBoundingClientRect().top;
    var cards = document.querySelectorAll('[id^="card"]');
    for (var i = 0; i < cards.length; i++) {
        var card = cards[i];
        card.addEventListener('dragstart',
            function(e) {
                e.dataTransfer.setData('text', e.target.id);
                x = e.clientX;
                y = e.clientY;
                var card = document.getElementById(e.target.id);
                offsetX = x - card.getBoundingClientRect().left;
                offsetY = y - card.getBoundingClientRect().top;
            }, false);
    }    
    // drop
    var dzone = document.getElementById('table');
    var zTop = 2;
    dzone.addEventListener('dragenter',
        function(e) {
            e.preventDefault();
        }, false);
    dzone.addEventListener('dragover',
        function(e) {
            e.preventDefault();
        }, false);
    dzone.addEventListener('drop',
        function(e) {
            e.preventDefault();
            rx = e.clientX - tableX;
            ry = e.clientY - tableY;
            var id = e.dataTransfer.getData('text');
            var card = document.getElementById(id);
            card.style.left = String(rx - offsetX) + 'px';
            card.style.top = String(ry - offsetY) + 'px';
            card.style.zIndex = ++zTop;
       }, false);
}

既知の問題点

カードがどこかへ行ってしまう(または、ドロップした位置から少しずれる)

onload で img 要素(カード)の親である dev 要素(テーブル)の座標を取得していますが、 画面をスクロールすると、ずれてしまいます。スクロール時にこの座標を更新する必要がありますが、 まだ対処していません。

この問題を回避するには、スクロール後にブラウザの再ロードボタンを押してください。

カードがテーブルからはみ出す

マウスポインタがテーブルの中であればドロップが実行されます。 テーブルの端でドロップするとカードがはみ出すことがあります。 この問題はあまり支障がないので今のところ直す予定はありません。