HTML5高阶实例之Drag&Drop

时间:2021-10-01 00:08:42

更新日期:2018年3月27日21:53:27

1、原生拖放-概述

对于拖放事件而言,默认情况下,浏览器不会在拖动期间改变被拖动元素的外观,但你可以自己修改。不过,大多数浏览器会为正被拖动的元素创建一个半透明的副本,这个副本始终随着光标移动。如下图所示。

>

默认情况下,图片、链接和文本是可以拖动的,也就是说img标签、a标签和选中的文字可以被拖动。

>

HTML5为所有HTML元素规定了一个draggable属性,img标签、a标签的默认值是true,其他元素默认值是false。

HTML5高阶实例之Drag&Drop

所有元素都支持放置目标事件,但默认是不允许放置的,即默认不会触发drop事件。如果想让某元素成为有效的放置目标,需要重写dragenter、dragover、drop事件。

2、使用注意事项

相关事件如下表格
事件名称 简要描述 是否必须重写
dragstart 按下并移动鼠标,被拖动元素此时触发该事件,触发一次
dragenter 元素拖动到放置目标上,触发一次
dragover 被拖动元素进入放置目标的范围内移动时,持续触发多次
drop 被拖动元素放入了放置目标中,触发一次
dataTransfer对象

dataTransfer对象,它是事件对象的一个属性,用于从被拖动元素放置目标传递字符串格式的数据。由于它是事件对象的属性(event.dataTransfer),所以只能在拖放事件的事件处理程序中访问。dataTransfer对象两个主要方法:
event.dataTransfer.setData();
event.dataTransfer.getData();

>

注意:在dragstart事件中通过event.dataTransfer.setData(‘text’,’wanshaobo’)保存在dataTransfer对象中的数据,只能在drop事件处理程序中读取event.dataTransfer.getData(‘text’)

3、实例一

概述:实现任务进度完成情况的可视化方案,包括未开始、进行中和已完成,任务标签可以在不同进度框中随意拖放。
代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>HTML5-drag&drop</title>
</head>
<style> *{ margin: 0; padding: 0; } #container{ /*font-size: 0;*/ clear: both; } .dropTarget{ width: 200px; height: 500px; background: #fff; border: 1px solid deeppink; /*display: inline-block;*/ margin-left: 20px; margin-top: 20px; float: left; text-align: center; } #draggable{ /*font-size: 0;*/ /*子元素人为设置为inline-block,父元素需要设置0字号以消除子元素间距*/ } .child{ width: 200px; height: 40px; color: #fff; font-size: 14px; text-align: center; line-height: 40px; border-radius: 20px; margin-top: 5px; } .child-img{ width: 100px; height: 100px; } .title{ margin-left: 20px; float: left; width: 200px; text-align: center; border: 1px solid #11baaa; line-height: 30px; border-radius: 15px; color: #aaccbb; } .clearBoth{ clear: both; } #top-title{ width: 640px; text-align: center; line-height: 50px; font-size: 22px; color: deeppink; font-weight: bolder; margin-left: 20px; } </style>
<body>
<div id="top-title">我的一天</div>
<div class="clearBoth">
    <div class="title">准备做的事情</div>
    <div class="title">正在做的事情</div>
    <div class="title">已做完的事情</div>
</div>
<div id="container">
    <div id="start" class="dropTarget" ondrop="drop(event)" ondragover="dragover(event)">
        <img id="five" class="child-img" src="./wsb.jpg" alt="" ondragstart="dragstart(event)">
        <div id="one" class="child" style="background: #ff7777" draggable="true" ondragstart="dragstart(event)">洗漱</div>
        <div id="two" class="child" style="background: #aaccbb" draggable="true" ondragstart="dragstart(event)">吃早饭</div>
        <div id="three" class="child" style="background: #ad8888" draggable="true" ondragstart="dragstart(event)">坐公交去上班</div>
        <div id="four" class="child" style="background: #f00aaa" draggable="true" ondragstart="dragstart(event)">到公司了打卡</div>
    </div>
    <div id="doing" class="dropTarget" ondrop="drop(event)" ondragover="dragover(event)">

    </div>
    <div id="end" class="dropTarget" ondrop="drop(event)" ondragover="dragover(event)">

    </div>
</div>
</body>
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript"> function dragstart(ev) { ev.dataTransfer.setData("Text",ev.target.id);//获取拖动元素实例 } function dragenter(ev) { ev.preventDefault();//dragenter事件的默认行为是该元素不允许其他元素放入,阻止默认行为之后,其他元素即可放入 } function dragover(ev) { ev.preventDefault();//dragover事件的默认行为是该元素不允许其他元素放入,阻止默认行为之后,其他元素即可放入 } //必须重写dragenter事件和dragover事件,阻止这两个事件的默认行为触发,才能触发drop事件 function drop(ev) { ev.preventDefault();//在Firefox3.5+中,放置事件的默认行为是打开被放到放置目标上的URL,为了兼容性,需要取消drop事件的默认行为 var data = ev.dataTransfer.getData("Text"); ev.target.appendChild(document.getElementById(data)); } </script>
</html>

作品如下

HTML5高阶实例之Drag&Drop

4、实例二

概述:子元素在父元素中随意拖放,但不能超出父元素。
分析:子元素超出父元素分为两种情况,第一,释放子元素时鼠标已经出界;第二,释放子元素时鼠标没有出界,但子元素出界;
代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>HTML5-drag&drop</title>
</head>
<style> *{ margin: 0; padding: 0; } .dropTarget{ width: 600px; height: 400px; background: #fff; border: 1px solid deeppink; margin-left: 20px; margin-top: 40px; } #child{ width: 100px; height: 60px; position: relative; box-sizing: border-box; background: #ff7777; } </style>
<body>
<div id="start" class="dropTarget" ondrop="drop(event)" ondragover="dragover(event)">
    <div  id="child" onmousedown="mousedown(event)" draggable="true" ondragstart="dragstart(event)" ondrag="drag(event)" ondragend="dragend(event)" ></div>
</div>
</body>
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript"> var relativeX = 0;//可移动元素相对于父元素的位置 var relativeY = 0; var mousedownX = 0;//鼠标在可移动元素上单击时,相对于该元素的位置 0 < x < 100 var mousedownY = 0; var draggableEle = document.getElementById('child'); function dragstart(ev) { //ev.dataTransfer.setData("Text",ev.target.id);//获取拖动元素实例 } function drag(ev) { } function mousedown(ev) { //ev对象下offsetX offsetY鼠标在该移动元素上的位置 mousedownX = ev.offsetX; mousedownY = ev.offsetY; } function dragend(ev) { //ev对象下screenX clientX pageX x都相同 //ev对象下clientY pageY y都相同,相对于可视区域的垂直位置;但screenY不同,screenY是相对于屏幕的垂直位置 //ev对象下offsetX offsetY鼠标移动的位移+鼠标在该移动元素上的位置 //DOM元素属性操作方法 getAttribute()、setAttribute()、removeAttribute() //DOM元素样式操作方法 elm.style.color 获取和赋值 relativeX += ev.offsetX - mousedownX; relativeY += ev.offsetY - mousedownY; //draggableEle.setAttribute('style','left:'+ relativeX + 'px;top:' + relativeY + 'px');//失效,因为重置了所有属性,丢失了宽高 //水平方向 if(ev.screenX <= 20 || ev.screenX >= 620){//鼠标出界 if(ev.screenX <= 20){//父元素相对于屏幕的margin-left: 20px; draggableEle.style.left = 0 + 'px'; relativeX = 0;//注意:此处没有px }else if(ev.screenX >= 620){//父元素宽600 + 20 draggableEle.style.left = 500 + 'px';//600-100 relativeX = 500;//注意:此处没有px }else{ draggableEle.style.left = relativeX + 'px'; } }else{//元素出界鼠标没有出界 if(ev.screenX <= mousedownX + 20){ draggableEle.style.left = 0 + 'px'; relativeX = 0;//注意:此处没有px }else if(ev.screenX >= mousedownX + 520){//600-100+20 draggableEle.style.left = 500 + 'px'; relativeX = 500;//注意:此处没有px }else{ draggableEle.style.left = relativeX + 'px'; } } //垂直方向 if(ev.pageY <= 20 || ev.pageY >= 440){//鼠标出界 if(ev.pageY <= 40){ draggableEle.style.top = 0 + 'px'; relativeY = 0;//注意:此处没有px }else if(ev.pageY >= 440){ draggableEle.style.top = 340 + 'px'; relativeY = 340;//注意:此处没有px }else{ draggableEle.style.top = relativeY + 'px'; } }else{//元素出界鼠标没有出界 if(ev.pageY <= mousedownY + 40){ draggableEle.style.top = 0 + 'px'; relativeY = 0;//注意:此处没有px }else if(ev.pageY >= mousedownY + 380){//400-60+40 draggableEle.style.top = 340 + 'px'; relativeY = 340;//注意:此处没有px }else{ draggableEle.style.top = relativeY + 'px'; } } } //必须重写dragenter事件和dragover事件,阻止这两个事件的默认行为触发,才能触发drop事件 function dragenter(ev) { ev.preventDefault();//dragenter事件的默认行为是该元素不允许其他元素放入,阻止默认行为之后,其他元素即可放入 } function dragover(ev) { ev.preventDefault();//dragover事件的默认行为是该元素不允许其他元素放入,阻止默认行为之后,其他元素即可放入 } //在Firefox3.5+中,放置事件的默认行为是打开被放到放置目标上的URL,为了兼容性,需要取消drop事件的默认行为 function drop(ev) { ev.preventDefault(); } </script>
</html>

作品如下

HTML5高阶实例之Drag&Drop