拖放(Drag 和 drop)是HTML5標準的組成部分
拖放
拖放是一種常見的特性辟犀,即抓取對象以后拖放到其他位置油湖。在 HTML5 中饰豺,拖放是標準的一部分晦闰,任何元素都可以被拖放嚣鄙。
瀏覽器支持
Internet Explorer 9 + 吻贿、Firefox、Opera 12 + 哑子、Chrome 以及 Safari 5 + 支持拖放舅列。
拖放API
draggable屬性
如果希望一個網(wǎng)頁元素可以被拖動,只需要將他的draggable屬性設置為true卧蜓,這個元素就可以拖動了帐要。
<div draggable="true">拖動我試試</div>
事件
拖動的過程會觸發(fā)許多事件,主要有下面這些:
-
dragstart
:網(wǎng)頁元素開始拖動時觸發(fā)弥奸。 -
drag
:被拖動的元素在拖動過程中持續(xù)觸發(fā)榨惠。 -
dragenter
:被拖動的元素進入目標元素時觸發(fā),應在目標元素監(jiān)聽該事件盛霎。 -
dragleave
:被拖動的元素離開目標元素時觸發(fā)赠橙,應在目標元素監(jiān)聽該事件。 -
dragover
:被拖動元素停留在目標元素之中時持續(xù)觸發(fā)愤炸,應在目標元素監(jiān)聽該事件期揪。 -
drop
:被拖動元素或從文件系統(tǒng)選中的文件,拖放落下時觸發(fā)规个。 -
dragend
:網(wǎng)頁元素拖動結(jié)束時觸發(fā)凤薛。
以上函數(shù)均可以指定回調(diào)函數(shù):
draggableElement.addEventListener('dragstart', function(e) {
alert('拖放開始姓建!')
console.log(e);
});
拖動過程中,鼠標移動事件將不會被觸發(fā)枉侧。
dataTransfer對象
拖動過程中引瀑,回調(diào)函數(shù)接受的事件參數(shù),有一個dataTransfer
屬性榨馁。它指向一個對象憨栽,包含了與拖動相關的各種信息。
dataTransfer對象的屬性:
- dropEffect:拖放的操作類型翼虫,決定了瀏覽器如何顯示鼠標形狀屑柔,可能的值為copy、move珍剑、link和none掸宛。
- effectAllowed:指定所允許的操作,可能的值為copy招拙、move唧瘾、link、copyLink别凤、copyMove饰序、linkMove、all规哪、none和uninitialized(默認值求豫,等同于all,即允許一切操作)诉稍。
- files:包含一個FileList對象蝠嘉,表示拖放所涉及的文件,主要用于處理從文件系統(tǒng)拖入瀏覽器的文件杯巨。
- types:儲存在DataTransfer對象的數(shù)據(jù)的類型蚤告。
dataTransfer對象的方法:
- setData(format, data):在dataTransfer對象上儲存數(shù)據(jù)。第一個參數(shù)format用來指定儲存的數(shù)據(jù)類型服爷,比如text杜恰、url、text/html等层扶。
- getData(format):從dataTransfer對象取出數(shù)據(jù)箫章。
- clearData(format):清除dataTransfer對象所儲存的數(shù)據(jù)烙荷。如果指定了format參數(shù)镜会,則只清除該格式的數(shù)據(jù),否則清除所有數(shù)據(jù)终抽。
- setDragImage(imgElement, x, y):指定拖動過程中顯示的圖像戳表。默認情況下桶至,許多瀏覽器顯示一個被拖動元素的半透明版本。參數(shù)imgElement必須是一個圖像元素匾旭,而不是指向圖像的路徑镣屹,參數(shù)x和y表示圖像相對于鼠標的位置。
draggableElement.addEventListener('dragstart', function(event) {
event.dataTransfer.setData('text', 'Hello World!');
});
上面代碼在拖動開始時价涝,在dataTransfer對象上儲存一條文本信息女蜈,內(nèi)容為“Hello World!”色瘩。當拖放結(jié)束時伪窖,可以用getData方法取出這條信息。
dataTransfer對象允許在其上存儲數(shù)據(jù)居兆,這使得在被拖動元素與目標元素之間傳送信息成為可能覆山。
實例
簡單拖放
/* html */
<ul id="drag-elements">
<li id="A" draggable="true"><img src="1.jpg" alt="" /></li>
<li id="B" draggable="true"><img src="2.jpg" alt="" /></li>
<li id="C" draggable="true"><img src="3.jpg" alt="" /></li>
<li id="D" draggable="true"><img src="4.jpg" alt="" /></li>
<li id="E" draggable="true"><img src="5.jpg" alt="" /></li>
<li id="F" draggable="true"><img src="6.jpg" alt="" /></li>
<li id="G" draggable="true"><img src="7.jpg" alt="" /></li>
<li id="H" draggable="true"><img src="8.jpg" alt="" /></li>
</ul>
/* css */
ul {
margin:0 auto;
width:800px;
}
ul:after{
content:"";
display:block;
clear:both;
}
li {
width:200px;
height:125px;
float:left;
background-color:#CCC;
text-align:center;
line-height:120px;
font-size:50px;
color:#F60;
}
.dragStart img {
width:200px;
height:125px;
}
/* js */
var dragElements = document.querySelectorAll('#drag-elements li');
var elementDragged = null;
for (var i = 0; i < dragElements.length; i++) {
dragElements[i].addEventListener('dragstart', function (e) {
e.dataTransfer.setData('text', this.id);
elementDragged = this;
});
dragElements[i].addEventListener('dragover', function (e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
elementDragged.setAttribute('class', 'dragStart');
return false;
});
dragElements[i].addEventListener('dragenter', function(e) {
e.preventDefault();
e.stopPropagation();
if (this.id != elementDragged.id) {
var tempInnerHtml = this.innerHTML;
this.innerHTML = elementDragged.innerHTML;
elementDragged.innerHTML = tempInnerHtml;
elementDragged.removeAttribute('class');
elementDragged = this;
}
});
dragElements[i].addEventListener('dragleave', function(e) {
e.preventDefault();
e.stopPropagation();
if (this.id != elementDragged.id) {
this.removeAttribute('class');
}
});
dragElements[i].addEventListener('drop', function (e) {
e.preventDefault();
e.stopPropagation();
var targetId = e.dataTransfer.getData('text');
elementDragged.removeAttribute('class');
return false;
});
dragElements[i].addEventListener('dragend', function (e) {
elementDragged = null;
});
};
拖放網(wǎng)元素
/* html */
<ul id="drag-elements">
<li draggable="true">A</li>
<li draggable="true">B</li>
<li draggable="true">C</li>
</ul>
<ul id="drop-target"></ul>
/* css */
ul{
min-height:100px;
background-color:#EEE;
margin:20px;
padding: 0;
}
ul li{
background-color:#CCC;
padding:10px;
margin-bottom:10px;
list-style: none;
}
/* js */
// 獲取dom元素
var target = document.querySelector('#drop-target');
var dragElements = document.querySelectorAll('#drag-elements li');
// 定義變量跟蹤被拖動的元素
var elementDragged = null;
// 對可以拖放的元素綁定 dragstart 和 dragend 事件
for (var i = 0; i < dragElements.length; i++) {
dragElements[i].addEventListener('dragstart', function(e) {
e.dataTransfer.setData('text', this.innerHTML);
elementDragged = this;
});
dragElements[i].addEventListener('dragend', function(e) {
elementDragged = null;
});
}
// 向目標元素綁定 dragover 事件,來處理元素拖動進入目標元素之后的事情
target.addEventListener('dragover', function(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
return false;
});
// 最后定義目標元素的 drop事件,將被拖動元素從原來的位置刪除
target.addEventListener('drop', function(e) {
e.preventDefault();
e.stopPropagation();
this.innerHTML = 'Dropped ' + e.dataTransfer.getData('text');
document.querySelector('#drag-elements').removeChild(elementDragged);
return false;
});
拖放文件
/* html */
<div id="target" title="拖動文件到這里">
<div id="content"></div>
</div>
/* css */
#target{
margin:10px;
min-height:100px;
max-height:600px;
background-color:#EEE;
border-radius:5px;
overflow:auto;
}
#content{
padding:10px;
font-size:18px;
line-height:25px;
}
/* js */
// 首先獲取拖動的目標元素和內(nèi)容展示區(qū)域
var target = document.querySelector('#target');
var contentDiv = document.querySelector('#content');
// 然后定義目標元素的dragover事件,定義了當文件進入目標元素后要做的事情
target.addEventListener('dragover', function(e) {
e.preventDefault();
e.stopPropagation();
e.dataTransfer.dropEffect = 'copy';
return false;
});
// 最后定義目標元素的drop事件,展示文件內(nèi)容
target.addEventListener('drop', function(e) {
e.preventDefault();
e.stopPropagation();
var fileList = e.dataTransfer.files;
if (fileList.length > 0) {
var file = fileList[0];
var reader = new FileReader();
reader.onloadend = function(e) {
if (e.target.readyState == FileReader.DONE) {
var content = reader.result;
contentDiv.innerHTML = "File: " + file.name + "\n\n" + content;
}
}
reader.readAsBinaryString(file);
}
});