在 HTML5 中,任何元素都能够被拖放
要使得一个元素是可拖动的,必须将它的 draggable
属性设置为 true
<div draggable="true">我是可以被拖动的</div>
在拖动元素的过程中,会触发相关的事件,与源对象(被拖动元素)相关的事件如下:
ondragstart
:开始拖动元素时触发ondrag
:元素正在拖动时触发ondragend
:完成元素拖动后触发
<!DOCTYPE html> <html> <head> <title>Drag Demo</title> <head> <style> #source-object { width: 50px; height: 50px; border: 1px solid red; background-color: red; } </style> <script> function dragstart(event) { console.log('dragstart') } function drag(event) { console.log('drag') } function dragend(event) { console.log('dragend') } </script> </head> </head> <body> <div id="source-object" draggable="true" ondragstart="dragstart(event)" ondrag="drag(event)" ondragend="dragend(event)" > </div> </body> </html>
另外,我们还能监听在元素释放时触发的事件,与目标对象(其实就是释放区域)相关的事件如下:
ondragenter
:当被拖动元素进入释放区域时触发ondragover
:当被拖动元素在释放区域移动时触发ondragleave
:当被拖动元素离开释放区域时触发ondrop
:当被拖动元素在释放区域释放时触发
<!DOCTYPE html> <html> <head> <title>Drop Demo</title> <head> <style> #source-object { width: 50px; height: 50px; border: 1px solid red; background-color: red; } #target-object { width: 100px; height: 100px; border: 1px solid blue; background-color: blue; } </style> <script> function dragenter(event) { console.log('dragenter') } function dragover(event) { // dragover 事件的默认行为是阻止数据或元素放置到其他元素中 // 如果想要避免这种情况,就必须阻止 dragover 的默认行为 // 只有这样,才能触发 drop 事件 event.preventDefault() console.log('dragover') } function dragleave(event) { console.log('dragleave') } function drop(event) { // 对于图片等元素,drop 事件的默认行为是以链接的形式打开 // 如果想要避免这种情况,就必须阻止 drop 的默认行为 event.preventDefault() console.log('drop') } </script> </head> </head> <body> <div>请将红色方框移入蓝色方框</div> <br /> <div id="source-object" draggable="true"></div> <br /> <div id="target-object" ondragenter="dragenter(event)" ondragover="dragover(event)" ondragleave="dragleave(event)" ondrop="drop(event)" > </div> </body> </html>
拖放事件还有一个新的属性 dataTransfer
,用于在源对象和目标对象之间传递数据
dataTransfer
它是一个对象,常用的方法有两个:
setData(key, value)
:在源对象设置数据getData(key)
:在目标对象获取数据
<!DOCTYPE html> <html> <head> <title>Drag And Drop Demo</title> <head> <style> #source-object { width: 50px; height: 50px; border: 1px solid red; background-color: red; } #target-object { width: 100px; height: 100px; border: 1px solid blue; background-color: blue; } </style> <script> // 源对象事件 function dragstart(event) { event.dataTransfer.setData('elemId', event.target.id) } // 目标对象事件 function dragover(event) { event.preventDefault() } function drop(event) { event.preventDefault() var elemId = event.dataTransfer.getData('elemId') var elem = document.getElementById(elemId) event.target.appendChild(elem) } </script> </head> </head> <body> <div>请将红色方框移入蓝色方框</div> <br /> <div id="source-object" draggable="true" ondragstart="dragstart(event)" > </div> <br /> <div id="target-object" ondragover="dragover(event)" ondrop="drop(event)"> </div> </body> </html>
最后来一个拖放在实际应用中的例子,实现文件拖拽上传功能
<!DOCTYPE html> <html> <head> <title>Drag And Drop Demo</title> <head> <style> #file-input { width: 300px; height: 100px; border-radius: 50px; border: 1px dashed black; display: flex; flex-direction: row; justify-content: center; align-items: center; } </style> <script> window.onload = function() { var fileInput = document.getElementById('file-input') fileInput.ondragover = function(event) { event.preventDefault() } fileInput.ondrop = function(event) { event.preventDefault() // 每次只获取第一个文件对象 var file = event.dataTransfer.files[0] // 检查 let isRightType = checkFileType(file) let isRightSize = checkFileSize(file) // 提示 if (isRightType && isRightSize) { alert('上传文件成功') } else if (!isRightType) { alert('只支持 DOCX、TXT、MD 文件格式') } else if (!isRightSize) { alert('文件不能大于 2 M') } } function checkFileType(file) { let allowedTypes = ['DOCX', 'TXT', 'MD'] let fileInfo = file.name.split('.') let fileType = fileInfo[fileInfo.length - 1].toUpperCase() return allowedTypes.includes(fileType) } function checkFileSize(file) { let maxSize = 2 * 1024 * 1024 let fileSize = file.size return fileSize <= maxSize } } </script> </head> </head> <body> <div id="file-input">请将文件拖动到此处</div> </body> </html>