質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

1回答

2260閲覧

ドラッグドロップでマウスを素早く動かした時対象が置き去りにされるのを改善したい

knight1220

総合スコア23

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/05/10 11:27

編集2020/05/12 16:44

ドラッグドロップの練習としてコードを書いてみました。
ゆっくりとマウスを動かしているときは実現したい挙動をしてくれるのですが、素早くマウスを動かすとドラッグしたい対象を置き去りにしてしまします。
置き去りにしないようにするにはどうすればいいでしょうか?
わかる方がいればご教授いただければ幸いです。

html

1<table class="box_cover" onMouseDown="return false;" onSelectStart="return false"> 2 <tr class="row1"> 3 <td class="r1_low1"> 4 <div id="box1" class="item">キリン1</div> 5 </td> 6 <td class="r1_low2"> 7 <div id="box2" class="item">ライオン1</div> 8 </td> 9 <td class="r1_low3"> 10 <div id="box3" class="item">ゾウ1</div> 11 </td> 12 </tr> 13 <tr class="row2"> 14 <td class="r2_low1"> 15 </td> 16 <td class="r2_low2"> 17 <div id="box7" class="item">ひよこ1</div> 18 </td> 19 <td class="r2_low3"> 20 </td> 21 </tr> 22 <tr class="row3"> 23 <td class="r3_low1"> 24 </td> 25 <td class="r3_low2"> 26 <div id="box8" class="item">ひよこ2</div> 27 </td> 28 <td class="r3_low3"> 29 </td> 30 </tr> 31 <tr class="row4"> 32 <td class="r4_low1"> 33 <div id="box10" class="item">ゾウ2</div> 34 </td> 35 <td class="r4_low2"> 36 <div id="box11" class="item">ライオン2</div> 37 </td> 38 <td class="r4_low3"> 39 <div id="box12" class="item">キリン2</div> 40 </td> 41 </tr> 42</table>

JavaScript

1let table=document.querySelector('.box_cover'); 2 3 function mdown(){ 4 event.target.classList.add('target'); 5 table.addEventListener('mousemove',mmove,false); 6 } 7 8 function mmove(){ 9 let clickPoint=event.target; 10 console.log(clickPoint); 11 let itemHeight=clickPoint.clientHeight/2; 12 let itemWidth=clickPoint.clientWidth/2; 13 14 if( clickPoint.classList.contains('target') ){ 15 16 if( clickPoint.classList.contains('item') ){ 17 let pageY=event.pageY; 18 let pageX=event.pageX; 19 clickPoint.style.top=`${pageY-itemHeight}px`; 20 clickPoint.style.left=`${pageX-itemWidth}px`; 21 clickPoint.classList.add('zIndex'); 22 clickPoint.classList.add('hover'); 23 } 24 25 } 26 27 28 table.addEventListener('mouseup',mup,false); 29 } 30 31 function mup(){ 32 table.removeEventListener('mousemove',mmove,false); 33 event.target.classList.remove('target'); 34 event.target.classList.remove('zIndex'); 35 } 36 37 table.addEventListener('mousedown',mdown,false);

Javascript

1 2 let table=document.querySelector('.box_cover'); 3 4 function mdown(){ 5 let clickPoint=event.target; 6 event.target.classList.add('target'); 7 8 table.addEventListener('mousemove',mmove,false); 9 if( clickPoint.classList.contains('target') ){ 10 11 if( clickPoint.classList.contains('item') ){ 12 clickPoint.classList.add('zIndex'); 13 clickPoint.classList.add('hover'); 14 } 15 16 } 17 table.addEventListener('mouseup',mup,false); 18 } 19 20 function mmove(){ 21 let clickPoint=event.target; 22 console.log(clickPoint); 23 //座標の読み取り 24 let itemHeight=clickPoint.clientHeight/2; 25 let itemWidth=clickPoint.clientWidth/2; 26 27 if( clickPoint.classList.contains('target') ){ 28 if( clickPoint.classList.contains('item') ){ 29 let pageY=event.pageY; 30 let pageX=event.pageX; 31 clickPoint.style.top=`${pageY-itemHeight}px`; 32 clickPoint.style.left=`${pageX-itemWidth}px`; 33 } 34 } 35 36 } 37 38 function mup(){ 39 table.removeEventListener('mousemove',mmove,false); 40 event.target.classList.remove('target'); 41 event.target.classList.remove('zIndex'); 42 } 43 44 table.addEventListener('mousedown',mdown,false);

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/05/10 11:29

「素早く」ってどれくらいでしょうか。 動かすことに集中しすぎてマウスONが離れてないとかないですか?
knight1220

2020/05/10 11:51

マウスダウンが離れているということはありません。 文章で説明するのは非常に説明するのは難しいのですが、 マウスを鋭く動かすといえばいいのでしょうか、ある程度ゆっくり動かしている間は実現したい挙動をしますが、一気ににマウスの移動量を増やすと対象が置き去りにされマウスポインタのみが移動してしまう状態です。 マウスダウンしたときにクラス(target)を付与しマウスアップしたときクラスを外すようにしているのですが置き去りにされた要素を検証画面で確認するとクラス名が残ったままの状態になっています。
guest

回答1

0

mousemove は、マウスポインタの移動中に連続的に発火するイベントですので
イベントリスナは、処理内容を座標の変化に応じた内容に特化して軽量化してください。

classList.add() と、table.addEventListener('mouseup',mup,false); は、 mousedown に移動しても動作するのではないでしょうか。
特に、後者の「イベントリスナのアタッチ」が連続的に行われる点は絶対に修正すべきです。
(際限のない多重登録が影響し、mouseup時に全リスナ実行(ラグ発生)するので、「置き去り」現象になっています)

マウス関連の mousedown, mousemove, mouseup を3つセットで用いるベントは
発火頻度も考慮して実装します。

  1. mousedown ... 初期化(2. 3. のイベントリスナをアタッチ)
  2. mousemove ... 座標取得と更新制御をできるだけ軽量な処理にする。

(リフレッシュレートが高い閲覧環境では何回かに1度にすることも検討する)
3. mouseup ... クリーンナップ(2. 3. のイベントリスナをデタッチ)

※ window 表示の PC用ブラウザなどは、押下したままウィンドウ枠の外でマウスボタンの開放なども発生しうるので focus / blur など、他のイベントを補助的に利用するなどして対策します。


追記)コメントを受けて
状態の変化に応じてイベントが発火していますので、実際の操作と紐付けて考えます。


ドラッグドロップの練習として

マウスイベントだけで実装する以外に、MDN:ドラッグ操作でもドラッグ&ドロップを学習できると思います
(ページ左のメニューにある「イベント」セクションで案内されている各イベントも要チェック)。

DragEvent は MouseEvent を継承しているので、ご質問のようなMouse操作と同様に座標取得ができます。

投稿2020/05/10 21:26

編集2020/05/11 19:58
AkitoshiManabe

総合スコア5434

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

knight1220

2020/05/11 18:09

回答ありがとうございます。 返信が遅くなってしまい申し訳ございません。 なんとなくですが、コードを書く順番が悪いためすごく処理が重くなっているのということは理解できました。 回答いただいた内容が理解できない点が多いのでまだまだ理解できていないのだなと実感しました。 とりあえずいただいた回答を理解できるようになるまで調べてみてそれでも理解できなければもう一度質問させていただきます。
knight1220

2020/05/11 18:14

早速質問になってしまうのですが、classList.add()がmousedown に移動しても動作するというのは'zIndex'と'hover'のことという認識で間違いないでしょうか?
AkitoshiManabe

2020/05/11 20:00

そのとおりです。 「実際の操作が、表示などに影響するタイミングがあるので、最適なタイミングになるように調整しましょう」ということです。
knight1220

2020/05/12 16:28

コードを修正してみたのですが、 置き去りされる現象は改善されませんでした。 他の書き方を考えたほうがいいのでしょうか? もしお時間がありましたらご教授いただければ幸いです。
AkitoshiManabe

2020/05/13 04:01

マウスイベントでの実装だと余分なイベント発火が起こるようですので、ドラッグ&ドロップ用にネイティブ実装されたイベントを使うほうが良いみたいですね。 https://developer.mozilla.org/ja/docs/Web/API/Document/drag_event のサンプルコードでは「This div is draggable」を移動できますが、置き去り現象は起こらないようです。 編集されたコードにおいて、イベントリスナ内で event.target のように event 情報を利用する場合はリスナの引数に event を指定しましょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問