ドラッグ可能なHTMLダイアログ(pure javascript)

 ファイルを開くダイアログならともかく、Itemの回転ダイアログなどは画面に被っていると、編集対象が隠れてダイアログ操作しずらくなってしまいます。

そこでモーダルダイアログ をドラッグで移動できるようにする必要があります。

HTMLのダイアログの場合、ドラッグ可能にするにはJSが必要で少しばかり手間です。

 


 

 

こちらに一案が紹介されていますが、これが動かなかったので別案を立てたものです。

 ドラッグで移動できるdialogタグをざっくりと作る

たぶんdialogやその親ページにかけられているCSSやHTML構造によって異なるのでしょう。

 

JS,CSS,HTML共にバニラな状態で動くはずです。

HTML

<dialog id='doc-save-dialog' draggable="true">
<form method="dialog">
<h1>Save?</h1>
document name:<br>
<input id='doc-name-input' type='text' class="default-focus-in-dialog"/>
<menu>
<button value="cancel">Cancel</button>
<button value="Save">Save</button>
</menu>
</form>
</dialog>

 大事なのはこれです。

draggable="true"

dialogタグにこれを付け忘れると、ドラッグはできるもののマウスでポイントが一発で上手く行かないダイアログになってしまいます。

かなり操作がストレスになります。


 JS

{
const dialogs = document.getElementsByTagName('dialog');
dialogs.forEach(dialog => {
let mouse = {
x: 0,
y: 0,
};
let pos = {
x: 0,
y: 0,
};
dialog.addEventListener('dragstart', evt => {
mouse.y = evt.pageY;
mouse.x = evt.pageX;
if(! dialog.style.top){
dialog.style.top = "0px";
dialog.style.left = "0px";
pos.y = 0;
pos.x = 0;
}else{
pos.y = parseInt(dialog.style.top.slice(0, -2), 10);
pos.x = parseInt(dialog.style.left.slice(0, -2), 10);
}
evt.dataTransfer.setDragImage(document.createElement('div'), 0, 0);
console.log('dragstart', evt.pageX, evt.pageY, mouse, pos, dialog.style.top);
});
dialog.addEventListener('drag', evt => {
if (evt.x === 0 && evt.y === 0) return;
const movey = (evt.pageY - mouse.y) * 2;
const movex = (evt.pageX - mouse.x) * 2;
dialog.style.top = (pos.y + movey) + 'px';
dialog.style.left = (pos.x + movex) + 'px';
console.log('drag', evt.pageX, evt.pageY, mouse, pos, dialog.style.top, movey);
});
});
}

drag開始とdrag中のマウス位置の差分をとって、drag開始時のDialog位置に足し合わせた新しい座標をセットしています。

mouseの移動量をそのまま差分で足していくと、mousemoveイベントの発行具合でだんだんズレていくので(このコードでは検証していませんが恐らく経験的に)、わざわざ初期値を保存して差分を計算しています。

 

TODO として、移動量に2を掛けないと上手く行かない理由は不明です。なのでこのコードは結果的に動いていますが何か間違っている気がします。


 最初は、

dialog.style.top = "0px";
dialog.style.left = "0px";

 がundefinedで存在しないので、セットしてしまいます。

初期位置はtop,left共に0pxらしいです。

2度め以降の移動では、dialogの初期位置もここから取るようにします。

 

 

本ドラッグ可能dialogコードは一応、手元の環境の中で

- 同ページ内に複数ダイアログで問題なし。 

- 開き直したダイアログが同じ位置に出る。

- 1度ドラッグして、再度ドラッグしてもズレたり問題は起こらない。

 ことを確認しています。

0 件のコメント:

コメントを投稿

Linuxコマンドライン上でSVGベクタ画像をJPG等へラスタライズ変換する

 Linuxコマンドライン上でSVGベクタ画像をJPG等へラスタライズ変換することができるが、上手く変換されない場合がある。   以前作った魔法陣イラスト素材をイラスト素材ストックサイトへ登録しようと思い立ち、改めて素材用にラスタライズ変換をかけようとした。   ラスタライズ変換...