HTML5ネイティブドラッグ&ドロップの詳しい解説 ドラッグ&ドロップ

序文

ドラッグ アンド ドロップは日常業務で頻繁に使用されます。つまり、オブジェクトを掴んで別の場所にドラッグします。現在、これは HTML5 標準の一部です。私はこの機能をいくつかの側面から学び、実践しました。

ドラッグアンドドロップ処理に対応するイベント

まずドラッグ アンド ドロップのプロセスを見てみましょう。

选中 --->  拖动  ---> 释放 

次に、このプロセス中に何が起こるかを段階的に見てみましょう。

選択された

HTML5 標準では、要素をドラッグ可能にするには、draggable 属性を true に設定します。
テキスト、画像、およびリンクはデフォルトでドラッグ可能であり、それらのドラッグ可能プロパティは自動的に true に設定されます。
画像とリンクは、マウスの左ボタンを押したまま選択してドラッグ アンド ドロップできます。
テキストは選択されている場合にのみドラッグ アンド ドロップできます。表示設定テキストのdraggable属性がtrueの場合は、マウスの左ボタンを押したまま直接ドラッグ&ドロップすることもできます。

ドラッグ可能属性: 要素がドラッグ可能かどうかを設定します。
文法:<element draggable="true | false | auto" >

  • true: ドラッグ可能
  • false: ドラッグを無効にします
  • auto: ドラッグが可能かどうかのブラウザ定義に従います。

引っ張る

拖动开始ドラッグ可能なすべての要素は、ドラッグ プロセス中に 3 つのプロセス--> 拖动过程中--> を経ます拖动结束

ターゲットを絞った イベント名 説明する
ドラッグされた要素 ドラッグスタート 要素のドラッグが開始されると発生します。
引っ張る 要素がドラッグされると繰り返し発生します
運ぶ ドラッグ操作が完了すると発火します
宛先オブジェクト もっと耐えられる ドラッグされた要素が、宛先要素が占める画面スペースに入るとトリガーされます。
ドラグオーバー ドラッグされた要素が宛先要素内にあるときにトリガーされます
ドラッグして残す ドラッグされた要素がドロップされずに宛先要素から離れるとトリガーされます。

ドラッグエンタイベントとドラッグオーバーイベントのデフォルトの動作は、ドラッグされた要素の受け入れを拒否することです。したがって、ブラウザのこのデフォルトの動作を防止する必要があります。e.preventDefault();

解放された

目的地に到着したら要素イベントを解放する

ターゲットを絞った イベント名 説明する
宛先オブジェクト 落とす ドラッグされた要素が目的の要素にドロップされるとトリガーされます。通常、ブラウザーのデフォルトの動作をキャンセルする必要があります。

ドラッグ リリースの例を選択してください

<!DOCTYPE HTML>
<html>

<head>
    <title>拖放示例-文本</title>
</head>
<style>
.src {
    display: flex;
}

.dropabled {
    flex: 1;
}

.txt {
    color: green;
}

.img {
    width: 100px;
    height: 100px;
    border: 1px solid gray;
}

.target {
    width: 200px;
    height: 200px;
    line-height: 200px;
    text-align: center;
    border: 1px solid gray;
    color: red;
}
</style>

<body>
    <div class="src">
        <div class="dragabled">
            <div class="txt" id="txt">
                所有的文字都可拖拽。
                <p draggable="true">此段文字设置了属性draggable="true"</p>  
            </div>
            <div class="url" id="url">
                <a href="http://weiqinl.com" target="_blank">我是url:http://weiqinl.com</a>
            </div>
            <img class="img" id="tupian1" src="img1.png" alt="图片1" />
            <img class="img" id="tupian2" src="img2.png" alt="图片2" />
        </div>
        <div id='target' class="dropabled target">Drop Here</div>
    </div>
    <script>
        var dragSrc = document.getElementById('txt')
        var target = document.getElementById('target')

        dragSrc.ondragstart = handle_start
        dragSrc.ondrag = handle_drag
        dragSrc.ondragend = handle_end

        function handle_start(e) {
          console.log('dragstart-在元素开始被拖动时候触发')
        }

      function handle_drag() {
            console.log('drag-在元素被拖动时候反复触发')
        }

      function handle_end() {
            console.log('dragend-在拖动操作完成时触发')
        }

        target.ondragenter = handle_enter
        target.ondragover = handle_over
        target.ondragleave = handle_leave

        target.ondrop = handle_drop

        function handle_enter(e) {
            console.log('handle_enter-当元素进入目的地时触发')
            // 阻止浏览器默认行为
            e.preventDefault()
        }

        function handle_over(e) {
            console.log('handle_over-当元素在目的地时触发')
            // 阻止浏览器默认行为
            e.preventDefault()
        }

        function handle_leave(e) {
            console.log('handle_leave-当元素离开目的地时触发')
            // 阻止浏览器默认行为
            // e.preventDefault()
        }

        function handle_drop(e) {
            console.log('handle_drop-当元素在目的地放下时触发')
            var t = Date.now()
            target.innerHTML = ''
            target.append(t + '-拖放触发的事件。')
            e.preventDefault()
        }
    </script>
</body>

</html>

ドラッグドロップイベントトリガー

ドラッグ アンド ドロップのプロセス全体で、上で説明したのは表面的な現象ですが、イベント プロセスの内部では他に何が起こるのでしょうか? 以下の DataTransfer オブジェクトを見てください。

データ転送オブジェクト

ドラッグ アンド ドロップ操作によってトリガーされるイベントと同時に送出されるオブジェクトは DragEvent です。これは MouseEvent から派生し、Event オブジェクトと MouseEvent オブジェクトのすべての機能を持ち、dataTransfer 属性を追加します。このプロパティは、ドラッグ アンド ドロップ データと対話情報を保存し、DataTransfer オブジェクトを返すために使用されます。
// DataTransfer dataTransfer = DragEvent.dataTransfer
DataTransfer オブジェクトによって定義されるプロパティとメソッドは数多くありますが、標準的なもののいくつかを見てみましょう。

属性 説明する
種類 読み取り専用プロパティ。これは、dragstart イベントで設定したドラッグ データ形式の配列を返します。書式設定の順序は、ドラッグ操作に含まれるデータの順序と同じです。IE10+、Edge、safari3.1、Firefox3.5+、および Chrome4 以降がこの属性をサポートしています。
ファイル ドラッグ操作でファイルのリストを返します。データ転送に使用できるすべてのローカル ファイルのリストが含まれます。ドラッグ操作にファイルのドラッグが含まれない場合、このプロパティは空のリストになります。
ドロップエフェクト 現在選択されているドラッグ アンド ドロップ操作のタイプを取得するか、操作を新しいタイプに設定します。これは常に、effectAllowed の可能な値 [none、move、copy、link] のいずれかに設定する必要があります。ドラッグオーバーイベントハンドラーのドロップターゲットにdropEffectを設定します。
効果許可 ドラッグ アンド ドロップ操作に許可される効果を指定します。これらのいずれかである必要があります [none、copy、copyLink、copyMove、link、linkMove、move、all、uninitialized] デフォルトは未初期化であり、すべての効果が許可されることを意味します。ondragstart ハンドラーにeffectAllowed属性を設定します。
方法 説明する
void setData(フォーマット, データ) ドラッグ操作のドラッグ データを指定されたデータとタイプに設定します。形式は MIME タイプにすることができます
文字列 getData(形式) 指定された形式でデータを返します。形式は setData() と一致します。
void clearData([フォーマット]) 指定されたタイプのドラッグ操作のデータを削除します。指定されたタイプのデータが存在しない場合、このメソッドは何も行いません。引数が指定されていない場合は、すべての種類のデータが削除されます。
void setDragImage(img, xOffset, yOffset) ドラッグ時にカーソルの下に表示する画像を指定します。ドラッグされたノードはデフォルトのイメージとして作成されるため、ほとんどの場合、これを設定する必要はありません。x パラメータと y パラメータは、それぞれ画像の水平オフセットと垂直オフセットを示します。
//IE10及之前版本,不支持扩展的MIME类型名
//Firefox 5版本之前,不能正确的将url和text映射为text/uri-list 和text/plain
var dataTransfer = event.dataTransfer;
//读取文本,
var text = dataTransfer.getData("Text");
//读取URL,
var url = dataTransfer.getData("url") || dataTransfer.getData("text/uri-list");

ドラッグドロップdataTransferの各種属性メソッドの例

ブラウザのサポート

とはいえ、ブラウザがサポートしていなければ意味がありません。

ページ上の要素を簡単にドラッグ アンド ドロップする方法。最小限の JavaScript が必要です。
最小限の js が必要です。ページ要素をドラッグする簡単な方法です。

引っ張る

ブラウザによるドラッグのサポート -- caniuse

note

  • dataTransfer.items Chrome のみでサポートされています
  • dropzoneプロパティ、現在ブラウザではサポートされていません
  • Firefox は.setDragImageあらゆるタイプの DOM 要素をサポートします。Chrome には、HTMLImageElementDOM およびブラウザの.setDragImageビューポートにアタッチされた DOM 要素が必要です。
    1. 部分的なサポートは、サポートdataTransfer.files または .typesオブジェクトがないことを意味します
    。 2. 部分的なサポートは、サポートがないことを意味します.setDragImage
    。 3. 部分的なサポートは、dataTransfer.setData / getData サポート形式が制限されていることを意味します

以下に、実際に私が遭遇したことは、ブラウザごとに標準の実装が異なるということです。

  • getData()Chrome 62.0 ブラウザでは、dropイベントでのみ有効になります。
  • メソッドを使用する場合setDragImage、指定された画像が存在しない場合、ドラッグ プロセスは次のようになります。
    1. dragstartSafari 11.0.1 ブラウザでは、イベントがトリガーされるだけですdragend
    2. Chrome、Opera、Firefox は通常どおり他のイベントをトリガーします。
  • ドラッグ アンド ドロップ操作ごとに、Firefox は新しいページを開くアクションを実行し、dataTransfer.getData()取得したコンテンツを自動的に検索します。
    回避策として、dropイベントに次を追加します e.stopPropagation();// 不再派发事件。解决Firefox浏览器,打开新窗口的问题
  • Opera 49 バージョンでは、デフォルトではリンクをドラッグできず、ドラッグする前にdraggableプロパティを に設定する必要があります。true
  • dropEffect と について effectAllowed 。
    1. effectAllowed ドラッグ アンド ドロップ操作が可能なエフェクトはわずか数個しかありません。dropEffect ドラッグ アンド ドロップ操作の特定の効果を設定できるのは、4 つの方法のうちの 1 つだけです。
    2. effectAllowedに設定するnone、要素のドラッグ アンド ドロップは許可されません。ただし、ブラウザごとにトリガーできるイベントは異なります。(注: Safari では要素をドラッグ アンド ドロップでき、すべてのイベントがトリガーされます)
    3. dropEffectに設定するnone、宛先要素へのドラッグ アンド ドロップは許可されません。
    4. の値が set である場合effectAlloweddropEffectその値がeffectAllowedの値と一致している必要があります。そうでない場合、ドラッグ効果は無効になり、ドラッグされた要素を宛先要素に配置することはできません。(注: Safari 11.0.1 は動作し、目的の要素にドラッグすることもできますが、これは標準を満たしていません)。

ドラッグ ドロップ データ転送属性メソッドの例
ドラッグ ドロップ イベントのトリガー

要約する

ネイティブ HTML5 のドラッグ アンド ドロップ API は、実際の作業では依然として多くの場面で遭遇するでしょう。
上記ではよく使われる API の一部のみを紹介しました。API は複雑ではありません。少し読んでいただければ、実践を通じて理解できるようになります。各ブラウザのパフォーマンスは若干異なる可能性がありますが、それでも誰もが標準に向けて成長していくと私は信じています。

 

おすすめ

転載: blog.csdn.net/delishcomcn/article/details/132400972