为了使元素可拖拽,需要在标签上设置draggable='true'
属性。
文本、图片和链接是默认可以拖放的,它们的draggable
属性自动被设置成了true
。
图片和链接按住鼠标左键选中,就可以拖放。
文本只有在被选中的情况下才能拖放。如果显示设置文本的draggable
属性为true
,按住鼠标左键也可以直接拖放。
拖拽元素上的事件
给元素设置draggable
属性后监听。
语法: <element draggable="true | false | auto" ></element>
true
: 可以拖动false
:禁止拖动auto
:默认值,使用浏览器定义的默认行为
在网页中,对于选中文本、图片和链接,浏览器会使用默认的拖动行为。当图片或者链接在拖动时,会自动设置图片或链接的地址为拖动数据(通过dragEvent.dataTransfer.getData('url')
,如果拖动的是链接,那么同时也可以通过dragEvent.dataTransfer.getData('text')
可获取);如果使用鼠标选中图片后拖动,那就不会设置图片的链接为拖动数据,当选中文本在拖动时,会自动设置文本为拖动数据(通过dragEvent.dataTransfer.getData('text')
获取).
<a
href="https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg"
>https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg</a
>
<script>
const a = document.getElementsByTagName("a")[0];
a.addEventListener("dragstart", (e) => {
// 均可以获取链接
console.log("text: " + e.dataTransfer.getData("text"));
console.log("url: " + e.dataTransfer.getData("url"));
e.preventDefault();
});![请添加图片描述](https://img-blog.csdnimg.cn/0b1a4c8add5445f5b7c4bea6b3196b61.gif)
</script>
链接拖动默认执行:
选中链接拖动默认执行:
<img
src="https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg"
width="100px"
height="100px"
/>
<script>
const img = document.getElementsByTagName("img")[0];
img.addEventListener("dragstart", (e) => {
// 只有getData('url')能获取
console.log("text: " + e.dataTransfer.getData("text"));
console.log("url: " + e.dataTransfer.getData("url"));
e.preventDefault();
});
</script>
图片拖动默认执行:
选中图片后拖动默认执行:
默认情况下,只有已选中的文本、图片、链接可以拖动。对其它的元素来说,必须按拖动机制的顺序设置 ondragstart
事件才能正常工作。
设置了draggable
为true
的元素不可选中
<div draggable="true">设置了draggable后不可选中</div>
<a
draggable="true"
href="https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg"
>https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg</a
>
<img
draggable="true"
src="https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg"
width="100px"
height="100px"
/>
设置了draggable
为true
不可选中:
注意:设置了
draggable
为true
的元素都不能通过常规的鼠标点击拖动选中。不过可以通过按下Alt
键同时点击来选中文本(通过dragEvent.dataTransfer.getData('text')
获取)。
draggbale
可以在所有元素上使用,包括图片和链接。不过,图片跟链接的draggable
默认为true
,所以通常只用来设置false
来禁止拖动。
链接设置 draggable=false
,如果行内同时存在图片,不会触发 dragstart
dragstart
该事件在拖拽元素或被选中的文本上触发,通常用来设置数据。
通过addEventListener
或者onDragstart
方法进行监听。
<div draggable="true">用于监听dragstart</div>
<script>
const div = document.getElementsByTagName("div")[0];
div.addEventListener("dragstart", (event) => {
console.log("dragstart");
console.log(event);
});
div.ondragstart = (event) => {
console.log("ondragstart");
console.log(event);
};
</script>
由于拖动事件会冒泡,因此可以单独监听父元素来获取多个子元素的拖动事件。
<div id="bubble-drag">
<a
href="https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg"
>https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg</a
>
<img
src="https://developer.mozilla.org/static/media/github-mark-small.348586b8904b950b8ea8.svg"
width="100px"
height="100px"
/>
<h1 draggable="true">拖动事件会冒泡</h1>
</div>
<script>
const bubbleDrag = document.getElementById("bubble-drag");
bubbleDrag.addEventListener("dragstart", (e) => {
console.log(e);
console.log(e.dataTransfer.getData("text"));
});
</script>
在dragstart
事件中,可以设置拖动数据,反馈图片及拖动效应。
拖拉事件用一个DragEvent
对象表示,该对象继承 MouseEvent
对象,因此也就继承了 UIEvent
和 Event
对象。DragEvent
对象只有一个独有的属性 DataTransfer
,其他都是继承的属性。DataTransfer
属性用来读写拖拉事件中传输的数据
所有的拖动事件都有一个dataTransfer
属性用来保存拖动数据。当元素拖动时,数据必须是能表明是哪个元素在被拖动,比如拖动选中文本时,拖动数据就是文本本身,拖动链接时拖动数据就是对应链接的地址。
拖动数据(drag data
)包含两个值,数据类型(推荐类型)跟数据值(都是string
类型).在拖动期间,通过setData
去设置拖动数据。
通过setData
设置拖动数据
<h1 draggable="true">通过setData设置拖动数据</h1>
<script>
const h1 = document.getElementsByTagName("h1")[0];
h1.addEventListener("dragstart", (e) => {
e.dataTransfer.setData("text/plain", "设置拖动数据");
console.log(e.dataTransfer.getData("text"));
});
</script>
一个拖动事件可以设置多个拖动数据。
h1.addEventListener("dragstart", (e) => {
e.dataTransfer.setData("text/plain", "设置拖动数据");
e.dataTransfer.setData("text/uri-list", "http://github.com");
console.log(e.dataTransfer.getData("text"));
console.log(e.dataTransfer.getData("url"));
});
当设置多个数据时,最好有一个text/plain
类型作为替补防止有些drop
目标不支持其他类型。
如果多次设置同一类型的数据,那么新数据会覆盖旧数据。
使用clearData
移除某类型数据或全部数据。
clearData
接受一个参数(数据类型),如果没传参数,就删除全部数据。
drag
该事件在拖拽元素上触发,在元素被拖动时反复触发
<h1 draggable="true">监听drag事件</h1>
<script>
const h1 = document.getElementsByTagName("h1")[0];
h1.addEventListener("drag", (e) => {
console.log(e);
});
</script>
dragend
该事件在拖拽元素上触发,在元素拖动完成时(释放鼠标键或按下escape
键)触发
<h1 draggable="true">监听dragend事件</h1>
<script>
const h1 = document.getElementsByTagName("h1")[0];
h1.addEventListener("dragend", (e) => {
console.log(e);
});
</script>
可放置元素
对于大多数浏览器页面和应用来说都是不能直接放置拖拽数据的。不过浏览器提供了几个事件用来声明可放置目标。
通过取消dragenter
和dragover
事件的默认执行动作就可以实现元素放置。
dragenter
该事件在拖动目标元素上触发,在拖动元素进入目标元素所占据的屏幕空间时触发
通常应该在这个事件的监听函数中,指定是否允许在当前节点放下(drop
)拖拉的数据。如果当前节点没有该事件的监听函数,或者监听函数不执行任何操作,就意味着不允许在当前节点放下数据(dragleave
、dragover
、drop
事件都不会触发)。在视觉上显示拖拉进入当前节点,也是在这个事件的监听函数中设置。
dragleave
该事件在拖动目标元素上触发,在拖动元素没有放下就离开目标元素时触发
dragover
该事件在拖动目标元素上触发,在拖动元素在目标元素内时持续触发
该事件的 target
属性是当前节点。该事件与dragenter
事件基本类似,默认会重置当前的拖拉事件的效果(DataTransfer
对象的dropEffect
属性)为none
,即不允许放下被拖拉的节点,所以如果允许在当前节点drop
数据,通常会使用preventDefault
方法,取消重置拖拉效果为none
。
drop
当被拖动元素或选中文本在目标元素里放下时触发,一般需要取消浏览器的默认行为。
<h1>拖拽元素</h1>
<div
style="width: 300px; height: 300px; border: 1px solid black"
id="drop-target"
>
可放置元素
</div>
<script>
const dropTarget = document.getElementById("drop-target");
dropTarget.addEventListener("dragover", (e) => {
e.preventDefault();
});
dropTarget.addEventListener("drop", (e) => {
console.log(e);
});
</script>
注意,如果当前节点不允许drop
,即使在该节点上方松开鼠标键,也不会触发该事件。如果用户按下Escape
键,取消这个操作,也不会触发该事件。该事件的监听函数负责取出拖拉数据,并进行相关处理
关于拖拉事件,有以下几点注意事项。
-
拖拉过程只触发以上这些拖拉事件,尽管鼠标在移动,但是鼠标事件不会触发。
-
将文件从操作系统拖拉进浏览器,不会触发 dragStart 和 dragend 事件。
-
dragenter
和dragover
事件的监听函数,用来指定可以放下(drop
)拖拉的数据。由于网页的大部分区域不适合作为drop
的目标节点,所以这两个事件的默认设置为当前节点不允许drop
。如果想要在目标节点上drop
拖拉的数据,首先必须阻止这两个事件的默认行为,或者取消这两个事件