更新情報
2020/06/30 コードの微修正をしました。
当ScriptではjQueryを使用しています。jQueryの設置方法は「jQueryの設定方法 - jQueryを使用するまでの手順 |【jQuery】 - IT the Best」をご覧ください。
ドラッグでHTML要素の位置を移動させる
mousemove(touchmove)イベントを使って、HTML要素のドラッグによる位置の移動を実装します。
※ブラウザによっては正常に動作しない可能性があります。
移動可能にする
var device = navigator.userAgent.match(/iphone|ipad|ipod|android/i) ? "sp" : "pc"; // デバイス確認
// デバイス別のイベント名を格納
var touchstart = device == "sp" ? "touchstart" : "mousedown";
var touchend = device == "sp" ? "touchend" : "mouseup";
var touchmove = device == "sp" ? "touchmove" : "mousemove";
/** @type {JQuery} */
var target=$(element); // 動かす対象
target.on(touchstart, function (event) {
if($(event.target).hasClass("immovable")){return} // 移動をさせないクラスが存在したら処理をさせない
event.preventDefault();
// 位置取得 デバイスに応じて取得対象を変える
let x = device == "sp" ? event.touches[0].clientX : event.clientX;
let y = device == "sp" ? event.touches[0].clientY : event.clientY;
$(this).data({ // タップ対象の移動に必要なデータを設定
"start": true, "move": false, // flag
"initialX": x, "initialY": y, // タップ位置
"top": this.offsetTop,"left": this.offsetLeft // 要素の初期位置
});
})
target.click(function (event) { // move後のリンク無効化
if ($(this).data("move")) {
$(this).data("move",false);
return false
}
});
// カーソルの移動イベントは、動かす要素ではなくdocument(ページ)全体に設定する
$(document).on(touchmove, (event) => { // move event
if ($(target).data("start")) { // targetがタップされていたら
event.preventDefault();
let x = device == "sp" ? event.touches[0].clientX : event.clientX;
let y = device == "sp" ? event.touches[0].clientY : event.clientY;
let moveX = x - target.data("initialX"); // ドラッグ距離 X
let moveY = y - target.data("initialY"); // ドラッグ距離 Y
if (moveX !== 0 || moveY !== 0) { // ドラッグ距離が0以外だったら
target.data("move", true).css("position", "absolute"); // moveフラグを設定
// 移動を可能にするためのスタイルを設定
}
// 初期位置にドラッグ距離を加算して移動させる
target[0].style.top = $(target).data("top") + moveY + "px";
target[0].style.left = $(target).data("left") + moveX + "px";
}
}).on(touchend, function (event) {
if ($(target).data("start")) { // targetがタップされていたら
$(target).data("start", false);
}
})
移動不可能にする(クラスの切り替え)
$(element).toggleClass("immovable");
jQuery 拡張版
jQuery.prototype.movable = function (startFunc, moveFunc, endFunc) {
let device = navigator.userAgent.match(/iphone|ipad|ipod|android/i) ? "sp" : "pc"; // デバイス確認
// デバイス別のイベント名を格納
let touchstart = device == "sp" ? "touchstart" : "mousedown";
let touchend = device == "sp" ? "touchend" : "mouseup";
let touchmove = device == "sp" ? "touchmove" : "mousemove";
/** @type {JQuery} */
let target; // 動かす対象
$(this).each(function (i, e) {
$(e).on(touchstart, function (event) {
if ($(e).hasClass("immovable")) { return } // 移動をさせないクラスが存在したら処理をさせない
event.preventDefault();
target = $(e); // 動かす対象
// 位置取得 デバイスに応じて取得対象を変える
let x = device == "sp" ? event.touches[0].clientX : event.clientX;
let y = device == "sp" ? event.touches[0].clientY : event.clientY;
$(this).data({ // タップ対象の移動に必要なデータを設定
"start": true, "move": false, // flag
"initialX": x, "initialY": y, // タップ位置
"top": this.offsetTop, "left": this.offsetLeft // 要素の初期位置
});
if (startFunc) { // タップ時の処理
startFunc(event,target);
}
})
$(e).click(function (event) { // move後のリンク無効化
if ($(this).data("move")) {
$(this).data("move", false);
return false
}
});
})
// カーソルの移動イベントは、動かす要素ではなくdocument(ページ)全体に設定する
$(document).on(touchmove, (event) => { // move event
if ($(target).data("start")) { // targetがタップされていたら
event.preventDefault();
let x = device == "sp" ? event.touches[0].clientX : event.clientX;
let y = device == "sp" ? event.touches[0].clientY : event.clientY;
let moveX = x - target.data("initialX"); // ドラッグ距離 X
let moveY = y - target.data("initialY"); // ドラッグ距離 Y
if (moveX !== 0 || moveY !== 0) { // ドラッグ距離が0以外だったら
target.data("move", true).css("position", "absolute"); // moveフラグを設定
// 移動を可能にするためのスタイルを設定
}
// 初期位置にドラッグ距離を加算して移動させる
target[0].style.top = target.data("top") + moveY + "px";
target[0].style.left = target.data("left") + moveX + "px";
if (moveFunc) { // 移動時の処理
moveFunc(event, target);
}
}
}).on(touchend, function (event) {
if ($(target).data("start")) { // targetがタップされていたら
target.data("start", false);
if (target.data("move")) { // 移動終了後の処理
if (endFunc) {
endFunc(event, target);
}
}
}
})
return this
}
jQuery.prototype.switchMovable = function () {
this.toggleClass("immovable");
}
要素の移動処理をjQueryのメソッドとして拡張し、引数にはタップ開始時、移動時、移動終了時のコールバック関数を用意しました。
使用例
要素(id="move-me")の移動 HTML CSS JS
移動させてください
移動可<div id="move-me" style="padding: 50px; background: skyblue;">移動させてください</div>
移動可<switch id="aaa-switch-movable" class="on"></switch>
$("switch#aaa-switch-movable").click((e)=>{
$(e.target).toggleClass("on");
$("#move-me").switchMovable();
})
$("#move-me").movable(function(e,target){ // タップ時の処理
target.css("border","1px solid black");
},function(e,target){ // 移動時の処理
target.css("box-shadow","0 0 10px 0 #000");
},function(e,target){ // 移動終了時の処理
target.css({
"border":"0",
"box-shadow":"unset",
"position":"unset","top":0,"left":0
});
})
補足
- move後のクリック無効は、リンクなどが設定されている要素の移動後のイベント(リンク先に飛ぶなど)を発生させないためです。
更新情報
- position:absoluteの設定するタイミングを移動を検知したときに変更。