HTML5 的拖拽介紹

jopen 13年前發布 | 74K 次閱讀 HTML5 前端技術

本文主要介紹與拖拽操作相關的對象及事件信息,但并不涉及太多的源碼演示。

一個簡單的示例

在html5中要實現拖放操作,相對于以前通過鼠標操作實現,要簡單得多,數據安全性也更有保障。只需要以下幾步即可。

  1. 給被拖拽元素添加draggable屬性,如果是文件拖放。
  2. 為目標元素添加一個dropzone屬性,這一步也不是必須的,可以省略。
  3. 在拖拽元素的dragstart中初始化相關的數據信息,主要是DataTransfer對象。
  4. 在目標元素的dragover事件中,取消其默認操作。
  5. 在目標元素的drop事件中,處理接受到的數據。
  6. 在被拖拽元素的dragend事件中,做善后工作。若沒有則可以省略。
  7. </ol>

    大致代碼如下:

        <div id="source" draggable="draggable">source</div>
        <div id="target">target</div>
        <script type="text/javascript">
        var target = document.getElementById('target');
        var source = document.getElementById('source');
        source.ondragstart = function(e){
          e.dataTransfer.effectAllowed = 'copyMove';
          e.dataTransfer.setData('test', 'testData');
        };
        target.ondragover = function(e){
          e.dataTransfer.dropEffect = 'move';
          e.preventDefault(); // 不能少
        };
        target.ondrop = function(e){
          var elem = document.createElement('a');
          elem.innerHTML = e.dataTransfer.getData('test');
          e.target.appendChild(elem);
        };
        </script>
    </section>

    draggable屬性

    draggable是一個枚舉屬性,用于指定一個標簽是否可以被拖拽。有以下四種取值:

    1. true:表示此元素可拖拽。
    2. false:表示此元素不可拖拽。
    3. auto:除img和帶href的標簽a標簽表示可拖拽外,其它標簽均表示不可拖拽。
    4. 其它任何值:表示不可拖拽。
    5. </ol> </section>

      dropzone屬性

      這個屬性用于接受拖拽元素的目標元素上,表示能接受的數據類型及操作方式。多個值用空格分開,不區分大小寫。其值有以下類型組成:

      • copy:表示將允許的元素放到該元素上時,會將拖拽數據復制到目標元素上。
      • link:表示將允許的元素放到該元素上時,將鏈接數據到目標元素上。
      • move:表示將允許的元素放到該元素上時,會將數據移動到目標元素上。
      • string:開頭的字符串,長度不能小于8個字符:表示能接受DataTransferItem.kind值為stringdata對象。
      • file:開頭的字符串,長度不能小于6個字符:表示能接受DataTransferItem.kind值為fileDataTransferItem.type的值匹配file:之后的字符的DataTransferItem的對象。
      • </ul> </section>

        相關的事件

        DragEvent接口定義

        DragEventMouseEvent接口繼承,其定義如下,與MouseEvent相比,只是多了個DataTransfer對象。所有針對拖拽的操作也是通過控制此對象來完成的。

            [Construct(DOMString type, optional DragEventInit eventInitDict)]
            interface DragEvent : MouseEvent
            {
              readonly attribute DataTransfer? dataTransfer;
            };
            /* 這是用于初始事件的參數定義 */
            dictionary DragEventInit : EventInit
            {
              // 從UIEvent繼承的屬性:
              Window? view = null;
              long detail = 0;
              // 從MouseEvent繼承的屬性:
              long screenX = 0;
              long screenY = 0;
              long clientX = 0;
              long clientY = 0;
              boolean ctrlKey = false;
              boolean shiftKey = false;
              boolean altKey = false;
              boolean metaKey = false;
              unsigned short button = 0;
              unsigned short buttons = 0;
              EventTarget? relatedTarget = null;
              // DragEvent添加的新屬性:
              DataTransfer? dataTransfer;
            }

        事件描述

        </tr> </thead>

        </tr> </tfoot>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr> </tbody> </table>

        目標元素是指當前鼠停留的元素,如要將A元素拖放到F元素上,中間經過的所有元素,在鼠標經過期間都是一個目標素,相應的事件都會被觸發,A元素本身就是第一個目標元素。

        </section>

        DataTransfer接口

        在HTML5中,為了實現在拖放過程中的數據交換,給所有的拖拽事件提供了一個DataTransfer屬性。通過此對象的方法和屬性來完善拖放功能。

            interface DataTransfer
            {
              attribute DOMString dropEffect;
              attribute DOMString effectAllowed;
              void setDragImage(Element image, long x, long y);
              readonly attribute DOMString[] types;
              DOMString getData(DOMString format);
              void setData(DOMString format, DOMString data);
              void clearData(optional DOMString format);
              readonly attribute DataTransferItemList items;
              readonly attribute FileList files;
            }

        effectAllowed和dropEffect

        這兩個屬性用于描述在拖拽過程中,鼠標顯示的樣式,受瀏覽器和操作系統的影響,鼠標顯示的圖標并不一致。

        effectAllowed表示此次拖拽允許顯示的鼠標樣式,可以是以下值:nonecopycopyLinkcopyMovelinklinkMovemovealluninitialized。只能在dragstart事件中更改此值。

        dropEffect表示此次拖拽過程中顯示的樣式,可以是以下幾個值:copymovelinknone。在具體的拖拽過程中,還受effectAllowed值限定,具體限定內容見下表,當dropEffect的值被設置為一個不屬于effectAllowed限定的值時,整個事件鏈將被中止,即后續事件都將不會被觸發,但不會發生任何錯誤提示。

        拖拽相關事件
        事件名稱 事件目標 可撤消? 存儲模式1 dropEffect值 默認操作 備注
        1.存儲模式是針對于DataTransfer對象的操作,具體數據見后表。
        dragstart 被拖拽元素 讀、寫 none 初始化操作 若調用preventDefault()函數取消此事件的默認行為,則拖拽功能將被取消。
        drag 被拖拽元素 保護模式 none
        在dragstart之后,釋放鼠標之前,不管鼠標是否移動,此事件不停地被觸發。
        dragenter 目標元素 保護模式 effectAllowed限定的值。 更換目標元素。 進入目標元素時,觸發一次。
        dragleave 離開前的目標元素 保護模式 none
        離開時觸發一次。
        dragover 目標元素 保護模式 effectAllowed限定的值 重置dropEffect為none,并中斷后續事件執行。 在dragenter之后,dragleave之前,不管是否移動,此事件都將不停地觸發。
        drop 目標元素 只讀模式 當前設定的值
        釋放鼠后,由目標元素觸發。
        dragend 被拖拽元素 保護模式 當前設定的值
        釋放鼠標后,由被拖拽元素觸發,順序在drop之后。

        </tr> </thead>

        </tr> </tfoot>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr> </tbody> </table> </section>

        setDragImage(image, x, y)

        這個函數用于設置鼠標移動過程中隨鼠標一起移動的效果圖,而不是鼠標指針的顯示效果。xy參數用于指定圖像相對于鼠標指針的位置;image參數用于指定圖像元素,若是一個img元素,則顯示圖像元素,否則將給定的元素轉換成一張圖像并顯示。

        該函數只能在讀寫模式(也就是dragstart事件)下有用,在其它事件中調用無效。若不調用此函數,則在拖拽時,被拖拽元素被轉換成一個圖處并當作一個效果圖顯示。

        </section>

        items屬性

        items的接口定義如下:

            interface DataTransferItemList
            {
              readonly attribute unsigned long length;
              getter DataTransferItem(unsigned long index); // items[index]
              deleter void(unsigned long index); // delete items[index]
              void clear();
              DataTransferItem? add(DOMString data, DOMString type);
              DataTransferItem? add(File data);
            }
            interface DataTransferItem
            {
              readonly attribute DOMString kind;
              readonly attribute DOMString type;
              void getAsString(FunctionStringCallback? _callback);
              File? getAsFile();
            }
            [Callback, NoInterfaceObject]
            interface FunctionStringCallback
            {
              void handleEvent(DOMString data);
            }

        從上面的定義不難看出:DataTransfer.items就是DataTransferItem的一個數組。DataTransferItemList僅僅是定義一套以數組形式存取DataTransferItem對象的接口。我們主要看一下DataTransferItem類的定義:

        • kind:表示數據的類型,只能是stringFile。單從字面就很好理解這兩個值代表的是什么意思。
        • type:實際數據的類型或是格式,一般用mimetype表示,但并不是強制mimetype格式。
        • getAsString(callback):當kind屬性為string時,在只讀或是讀寫模式下,可以通過回調函數處理此對象關聯的實際數據。
        • getAsFile():當kindfile是,通過此函數能獲取真實的數據,否則返回null,只在只讀或是讀寫模式下有效。
        • </ul>

          在非讀寫模式下刪除DataTransferItemList中的數據,會返回InvalidStateError錯誤。若是在非讀寫模式下添加數據,則不執行任何操作。DataTransfer.setData則是對這兩個函數的封裝(根據第二個參數決定是刪除還是添加)。

          </section>

          types屬性

          返回根據下列步驟產生的字符串集合(DOMStringList):

          1. 產生一個空的DOMStringList對象L。
          2. 遍歷DataTransfer.items對象。
          3. DataTransfer.items的子項的kind的值為string,則將該項的type值添加到L對象中。
          4. DataTransfer.items的子項的kind的值為file,則向L對象添加"Files"字符串。
          5. 返回L對象
          6. </ol> </section>

            getData(format)

            getData是從DataTransfer.items中查找數據。返回符合以下條件的數據:

            1. DataTransferItem.kindstring
            2. DataTransferItem.type的值等于format參數
            3. </ol>

              如果沒有找到匹配的或是處于保護模式下,則返回一個空字符串。

              參數format在傳遞到函數內部之前,都會被轉換成小寫字符,且如果參數值為text或是url,則會被轉換成text/plaintext/uri-list

              </section>

              setData(format, data)

              setData用于向DataTransfer.items中添加或刪除一條數據:

              當沒有指定第二個參數data時,則是從DataTransfer.items中刪除符合以下條件的數據:

              1. kind等于string
              2. type等于參數format
              3. </ol>

                當指定第二個參數data時,則是向DataTransfer.items中添加數據,新添加的數據格式如下:

                1. kind的值為string
                2. type的值為format
                3. data參數作為DataTransferItem的實際值。
                4. </ol>

                  參數format在傳遞到函數內部之前,都會被轉換成小寫字符,且如果參數值為text或是url,則會被轉換成text/plaintext/uri-list

                  如果不處于讀寫模式下,則不做任何操作。

                  </section>

                  clearData()

                  清除所有kind值為string的項。只在讀寫模式下起作用。

                  </section></section>

                  存儲模式

                  存儲模式決定了DataTransfer各項內容是否可用。下表列出相關的信息,其中Y表示可用,N表示不可用。

        effectAllowed與dropEffect對照表
        effectAllowed dropEffect
        1:根據用戶所使用的平臺不同,可能會出現的值,如在windows下,copyMove的effectAllowed值,默認為copy操作,在按shift鍵時,則會變成move操作。
        none none
        copy copy
        copyLink copy或是link1
        copyMove copy或是move1
        all copy、link1或是move1
        link link
        linkMove link或是move1
        move move
        uninitialized,被拖拽為一個文本框中選中的內容? move或是copy1,link1
        uninitialized,被拖拽對象為一個普通選中項? copy或是link1,move1
        uninitialized,被拖拽對象為一個帶鏈接的a元素 link或是copy1,move1
        其它情況 copy或是link1,move1

        </tr> </thead>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr>

        </tr> </tbody> </table> 來自:http://blog.830725.com/post/html5-drag-and-drop-intro.html

         本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
         轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
         本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
        存儲模式與DataTransfer各項的關系

        讀寫 只讀 保護
        dropEffect 只在dragenterdragover事件中可更改,其它事件中只可讀取。
        effectAllowed 只在dragstart事件中起作用
        items 對items的操作詳細情況參考后面的setData函數
        types 僅在dragenterdragoverdrop三個事件中可獲取此值
        setData Y N N
        getData Y Y N
        clearData Y N N
        DataTransferItem.getAsString Y Y N
        DataTransferItem.getAsFile Y Y N
sesese色