拖放事件可以让开发者控制拖放操作的方方面面,关键的部分是确定每个事件是在哪里触发的,有的事件在被拖放元素上触发,有的事件则在放置目标上触发。
当某个元素被拖动时,会按顺序触发以下事件:
事件 | 说明 |
---|---|
dragstart | 按住鼠标不放开始移动鼠标时触发 |
drag | 元素正在被拖动时触发 |
dragend | 停止拖动时触发 |
在把元素拖动到一个有效的放置目标上时,会依次触发以下事件:
事件 | 说明 |
---|---|
dragenter | 被拖动的元素进入目标容器时触发 |
dragover | 被拖拽元素在目标容器内拖动时触发 |
dragleave | 被拖动元素离开目标容器时触发 |
drop | 被拖动元素放到了目标容器上触发 |
如果我们想让一个元素可以被拖放,还要为该元素添加dragabble
属性
dataTransfer
对象实现了拖动操作中的数据传输,用于从被拖动元素向放置目标传递字符串数据。因为这个对象是event
的属性,所以在拖放事件的事件处理程序外部无法访问dataTransfer
。
该对象内部有以下属性和方法:
事件 | 说明 |
---|---|
dropEffect | 可以告诉浏览器允许哪种放置行为,获取当前选定的拖放操作类型或者设置的为一个新的类型。值必须为none , copy , link 、move 。 |
effectAllowed | 表示对被拖动元素是否允许dropEffect ,提供所有可用的操作类型。必须是none , copy , copyLink , copyMove , link , linkMove , move , all 、uninitialized 之一。 |
files | 包含数据传输中可用的所有本地文件的列表。如果拖动操作不涉及拖动文件,则此属性为空列表。 |
items | 提供一个包含所有拖动数据列表的DataTransferItemList 对象。 |
types | 一个提供dragstart 事件中设置的格式的strings 数组。 |
clearData() | 删除与给定类型关联的数据。类型参数是可选的。如果类型为空或未指定,则删除与所有类型关联的数据。如果指定类型的数据不存在,或者data transfer 中不包含任何数据,则该方法不会产生任何效果。 |
getData() | 检索给定类型的数据,如果该类型的数据不存在或data transfer 不包含数据,则返回空字符串。 |
setData() | 设置给定类型的数据。如果该类型的数据不存在,则将其添加到末尾,以便类型列表中的最后一项将是新的格式。如果该类型的数据已经存在,则在相同位置替换现有数据。 |
setDragImage() | 用于设置自定义的拖动图像。 |
HTML5
在所有HTML
元素上规定了一个draggable
属性,表示元素是否可以拖动。
图片和链接的draggable
属性自动被设置为true
,而其他所有元素此属性的默认值为false
。如果想让其他元素可拖动,或者不允许图片和链接被拖动,都可以设置这个属性。
示例代码:
<!-- 禁止拖动图片 -->
<img src="smile.gif" draggable="false" alt="Smiley face">
<!-- 让元素可以拖动 -->
<div draggable="true">...</div>
设置一个可以拖拽的元素:
<div id="draggable" draggable="true">Drag me!</div>
#draggable {
width: 100px;
height: 100px;
background-color: #3498db;
color: #fff;
text-align: center;
line-height: 100px;
cursor: move;
position: absolute;
}
const draggableElement = document.getElementById('draggable');
let offsetX, offsetY;
draggableElement.addEventListener('dragstart', function (event) {
// 拖动开始时计算鼠标位置与元素左上角的偏移,并记录
offsetX = event.clientX - draggableElement.getBoundingClientRect().left;
offsetY = event.clientY - draggableElement.getBoundingClientRect().top;
});
draggableElement.addEventListener('drag', function (event) {
// 计算元素应该移动到的位置
const x = event.clientX - offsetX;
const y = event.clientY - offsetY;
// 更新元素位置
draggableElement.style.left = x + 'px';
draggableElement.style.top = y + 'px';
});
draggableElement.addEventListener('dragend', function (event) {
const x = event.clientX - offsetX;
const y = event.clientY - offsetY;
// 拖动结束之后更新元素的位置
draggableElement.style.left = x + 'px';
draggableElement.style.top = y + 'px';
});