LoginSignup
0
0

JavaScript 第10回 ウィンドウをドラッグ&ドロップで移動(マウス、タッチ両対応)

Last updated at Posted at 2024-01-26

はじめに

今回は、第9回で作成したモードレスウィンドウをドラッグ&ドロップで移動できるようにしたものをタッチにも対応するようにします。
モードレスウィンドウの作成については、第9回の記事を参照ください。
第9回の記事でコメントをいただいて、mouse・・ の代わりに、pointer・・ が使えるということを伺いましたので、それに対応します。
また、関数名もコメントいただきましたので修正します。

第9回に記載していた「もう少し改善の余地があることがわかりましたので、そのあたりは今後また記事にしたい と思います。」については、引き続き保留とし、今回はマウス、タッチ両対応にフォーカスします。

申し訳ありません。
ドラッグ&ドロップの動作については、すでに第9回の記事に記載していますので、本記事はほぼ書き換えたソースだけの紹介です。

申し訳ありません。
タッチ対応のPCやタブレットを持ち合わせていないため、タッチ対応と記載しながら、タッチの動作については確認できておりませんので、ご容赦ください(mouseeventがタッチで動作するか心配)。

今回実施する内容

モードレスウィンドウを マウス、および、タッチによる ドラッグ&ドロップで移動できるようにします。
dandd.gif

ソースコード(Git Hub)

環境

OS: Windows 11 JP (64bit)
Microsoft Edge:バージョン 120.0.2210.91 (公式ビルド) (64 ビット)

参考

pointerdown
pointermove
pointerup
pointerleave
MouseEvent: pageX プロパティ
MouseEvent: pageY プロパティ
MouseEvent: offsetX プロパティ
MouseEvent: offsetY プロパティ

用語

なし

動作の仕組み

第9回の記事に記載のため省略します。

MouseEvent: pageXなどで、ポインターの位置を取得します。これがタッチ動作でも同様か動作確認できておりません。
しかし、UE_Eventにマウス、タッチ共通のUIやタッチ用のUIは存在していないようですので、動作するのではないかと想像しています。

ウィンドウをドラッグ&ドロップで移動する具体的な実装

ソース

第9回の記事とほぼ同じです。
以下の部分だけが異なります。

  • ファイル名(単なる区別のため)
  • イベント
第9回 第10回
mousemdown pointerdown
mousemove pointermove
mouseup pointerup
mouseleave pointerleave
  • 関数名(第9回記事でコメントを受けたため修正)
  • 関数のコメント(タッチ対応のため文言修正)
modeless_drag_pointer.htmlのソースコード(ファイル名のみ変更あり)
modeless_drag_pointer.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Position</title>
    <link rel="stylesheet" href="modeless_drag_pointer.css" type="text/css">
    <script src="modeless_drag_pointer.js" defer></script>
</head>
<body>
    <div>- 画面表示 -</div>
    <div id="showTop">画面上部表示</div>
    <div id="topDiv">
        <div class="closeCircle" id="closeTop">×</div>
        画面の上に表示されます。
    </div>
</body>
</html>
modeless_drag_pointer.cssのソースコード(変更なし)
modeless_drag_pointer.css
.closeCircle {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 18px;
  text-align: center;
  position: absolute;
  right: 3px;
  top: 2px;
}

#topDiv .closeCircle {
  background-color: orange;
}

#topDiv {
  visibility: hidden;
  background-color:yellow;
  position: absolute;
  width: 300px;
  height: 100px;
  top: 0px;
  left: 20%;
}
modeless_drag_pointer.jsのソースコード(変更あり)
modeless_drag_pointer.js
/** modeless用の設定 */
document.getElementById("showTop").addEventListener("click", () => {
    showWindow("topDiv");
});

document.getElementById("closeTop").addEventListener("click", () => {
    closeWindow("topDiv");
});

function showWindow(divId) {
    document.getElementById(divId).style.visibility = "visible";
}

function closeWindow(divId) {
    document.getElementById(divId).style.visibility = "hidden";
}

/** ドラッグ&ドロップで移動する設定*/
var elemId;             //ドラッグした要素のId
var elemOffsetX;        //ドラッグした要素のoffsetX
var elemOffsetY;        //ドラッグした要素のoffsetY

//"topDiv"にマウスダウン、マウスアップ時のEventLisnterを追加。
document.getElementById("topDiv").addEventListener("pointerdown", handlePointerDown);
document.getElementById("topDiv").addEventListener("pointerup", handlePointerUp);

/**
 * マウス、もしくは、タッチで要素がアクティブになった時に、
 * - その座標の保存。
 * - ドラッグによる移動時のEventListnerを追加。×画面の上に表示されます。
 * - ドラッグしながらポインタが画面外移動時のEventListenerを追加。
 * 
 * @param {object} event コールバック関数は発生したイベントを説明するEventに基づくオブジェクト。
 */
function handlePointerDown(event) {
    getElemOffset(event);
    document.getElementById(elemId).addEventListener("pointermove", dragWindow);
    document.body.addEventListener("pointerleave", cancelDragWindow);
}

/**
 * マウス、もしくは、タッチで要素が非アクティブになった時に、
 * - ドラッグによる移動時のEventListenerを削除。
 * 
 * @param {object} event コールバック関数は発生したイベントを説明するEventに基づくオブジェクト。
 */
function handlePointerUp(event) {
    document.getElementById(elemId).removeEventListener("pointermove", dragWindow);
    document.body.removeEventListener("pointerleave", cancelDragWindow);
}

/**
 * 要素のオフセット(offsetX、offsetY)、およびその要素のIdを保存。
 * 
 * @param {object} event コールバック関数は発生したイベントを説明するEventに基づくオブジェクト。
 */
function getElemOffset(event) {
    elemOffsetX = event.offsetX;
    elemOffsetY = event.offsetY;
    elemId = event.target.id;
}

/**
 * マウス、もしくは、タッチで要素をドラッグ時に、ドラッグした要素を移動。
 * 
 * @param {object} event コールバック関数は発生したイベントを説明するEventに基づくオブジェクト。
 */
function dragWindow(event) {
    document.getElementById(elemId).style.left = event.pageX - elemOffsetX + "px";
    document.getElementById(elemId).style.top = event.pageY - elemOffsetY + "px";
}

/**
 * body外移動時のdragWindowのEventListenerを削除。
 * 
 * @param {object} event コールバック関数は発生したイベントを説明するEventに基づくオブジェクト。
 */
function cancelDragWindow(event) {
    document.getElementById(elemId).removeEventListener("pointermove", dragWindow);
    document.body.removeEventListener("pointerleave", cancelDragWindow);
}

おわりに

今回は、第9回の記事のマウスで「ウィンドウをドラッグ&ドロップで移動」をタッチにも対応するようにしました。
マウスでの動作は変わりがないことを確認しましたが、タッチは未確認です。
今後こちらのソースをベースに引き続きモーダルウィンドウを作っていこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0