前端學習(八十五) 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時,我們才認為這個是一個拖拽行為
案例需要思考寫,稍後上傳程式碼