1. 程式人生 > >前端學習(八十五) DOM-拖拽(Dom)

前端學習(八十五) DOM-拖拽(Dom)

主要的應用場景:拖拽排序,拖拽上傳檔案,頭像拖拽裁剪

拖拽的流程:

確定可拖拽的內容 -> 開始拖拽 -> 拖拽過程(可放置內容/不可放置內容) -> 結束拖拽

涉及的知識點:

  • 確定可拖拽的內容:draggable屬性標識哪些內容是可拖拽的
  • 開始拖拽:觸發一個dragstart事件,標識開始拖拽了
  • 拖拽過程:在拖著的過程中不斷的觸發,drag,dragenter,dragleave,drapover事件
  • 結束拖拽:容器會觸發drop事件,拖拽內容觸發一個dragend事件

確定可拖拽的內容

首先我們必須在那些可拖拽的內容上設定一個draggable屬性,表示這個元素是可以拖拽的

開始拖拽

當滑鼠移動時,這個元素會觸發一個dragstart事件,表示拖拽開始了

拖拽過程

當拖拽過程中,拖拽的元素會不斷的觸發drag事件,而當離開容器後,容器會觸發一個dragleave事件,當把拖拽元素拖動到另外一個容器時,這個容器會觸發dragenter事件,當這個元素在新容器內部不斷拖動的時候,這個容器會不斷觸發dragover事件,當鬆開滑鼠後,這個元素會觸發一個drop事件,同時拖拽元素自身會觸發一個dragend事件

 

draggable

直接設定在元素上,有三個值,true(可拖拽),false(不可拖拽),auto(自動根據瀏覽器識別,預設,通常預設可以拖拽的元素有img,帶圖片的object,帶href屬性的<a>,選中的文字)

            <ol>
                <li draggable="true">蘋果</li>
                <li draggable="false">栗子</li>
                <li draggable="auto">橙子</li> <!--預設是auto-->
            </ol>

DragEvent

dataTrabsfer.dropEffect

這個代表了滑鼠這個圖示的變化過程,例如可拖拽的,連結的,禁止的,它的值有

none:表示不可拖拽的,這個拖拽是無效的

move:表示當鬆開滑鼠的時候,要將拖拽的內容放置到新的容器中

copy:表示當鬆開滑鼠的時候,要將拖拽的內容複製一份到新的容器中

link:表示作為一個連結地址,可以是開啟,顯示等等

dataTrabsfer.effectAllowed

定義這個被拖拽的內容的效果是什麼樣的,比如只能被copy,只能被move還是即可以是copy也可以是move

這個屬性只能在dragstart這個事件中設定,在開始拖拽的時候要確定效果是,move還是copy還是什麼,這個屬性用於在dragenter和dragover事件中初始化dropEffect

允許的值為:none,copy,copyLink,copyMove,link,linkMove,move,all,uninitialized

dataTrabsfer.setDragImage(element,x,y)

就是在拖動的過程中,在滑鼠旁邊有一個快照,顯示的是拖拽的內容,可以通過這個知道正在拖拽的內容是什麼,預設瀏覽器會自動生成一個

  • element:傳入的快照影象
  • x和y引數:快照的偏移量,x代表滑鼠的點選位置距離圖片左側邊框的距離,y代表滑鼠的點選位置距離圖片頂部的距離

這個事件也只可以在dragstart事件中設定

dataTrabsfer.setData(format,data)

format

  • 會自動轉成小寫字元
  • 每個item中的type
  • 同一種format存一份資料
  • 以下format值會自動進行轉換,text->text/plain,url->text/uri-list

同樣,這個事件也只能在dragstart事件中儲存拖拽資料

dataTrabsfer.getData(format,data)

format

  • 會自動轉成小寫字元
  • 每個item中的type
  • 同一種format存一份資料
  • 以下format值會自動進行轉換,text->text/plain,url->text/uri-list

同樣,這個事件也只能在dragstart事件中儲存拖拽資料

 

案例

將列表中的項拖拽到另一個列表中

       <div>
            <ol id="one" ondragstart="dragSatrtHandler(event)" ondragend="dragEndHandler(event)">
                <li draggable="true" data-value='蘋果'>蘋果</li>
                <li draggable="true" data-value='栗子'>栗子</li>
                <li draggable="true" data-value="橙子">橙子</li> <!--預設是auto-->
            </ol>
            <ol id="two" ondragover="dragOverHandler(event)" ondrop="dropHandler(event)">

            </ol>
        </div>
        <script>
            function dragSatrtHandler(event) {
                console.log(event.target);
                if(event.target instanceof HTMLLIElement){
                    let value=event.target.dataset.value;
                    console.log(value);
                    console.log(event.dataTransfer.effectAllowed);
                    
                    event.dataTransfer.effectAllowed = 'move';
                    console.log(event.dataTransfer.effectAllowed);
                    event.dataTransfer.setData('text/plain',value);
                    //event.dataTransfer.effectAllowed = 'move';

                }
                else{
                    event.preventDefault()
                }
            }
            function dragEndHandler(event){
            
                if(event.dataTransfer.dropEffect === 'move'){
                    event.target.parentNode.removeChild(event.target);
                }
                else{
                    console.log('型別為:'+event.dataTransfer.dropEffect);
                }
            }
            function dragOverHandler(event) {
                event.preventDefault();
            }
            function dropHandler(params) {
                console.log('li');
                
                let li= document.createElement('li');
                li.textContent=params.dataTransfer.getData('text/plain');
                params.target.appendChild(li);
            }

但是這個相容有問題,移動端基本不相容,而PC端相容也不是特別好,IE的相容很差,因此需要考慮到相容方案

 

相容方案

簡單的說,就是用MouseEvent上的mousedown,mousemove,mouseover,mouseout,mouseup來模擬drop的各種操作

大致的對應關係

如果元素只有mousedown,那麼我們不認為它是一個拖拽行為,只有當既有mousedown和mousemove時,我們才認為這個是一個拖拽行為

案例需要思考寫,稍後上傳程式碼