实现元素拖放的两种方式:
- 传统方式:通过监听鼠标事件,获取元素移动的位置,计算并赋值到目标位置上(依赖position的定位样式);
- HTML5方式:HTML5 中提供了直接拖放的 API,极大的方便我们实现拖放效果,只需要通过监听元素的拖放事件就能实现各种拖放功能。想要拖放某个元素,必须设置该元素的
draggable
属性为 true
一、传统方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.dialog{
position: absolute;
left: 100px;
top:200px;
width:200px;
height: 300px;
}
.title{
width: 100%;
height: 15%;
background-color: lightseagreen;
text-align: center
}
.itbody{
width: 100%;
height: 90%;
background-color: lightgoldenrodyellow
}
</style>
</head>
<body>
<div class="dialog">
<div class="title">title</div>
<div class="itbody"></div>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
var isMouseDown = false;
var lastPoint = {}
$('.title').on('mousedown',function(e){
isMouseDown = true;
lastPoint.x = e.pageX;
lastPoint.y = e.pageY
})
$(document).on('mousemove',function(e){
if(isMouseDown){
var targetX =parseInt($('.dialog').css("left")) + e.pageX - lastPoint.x
var targetY =parseInt($('.dialog').css("top")) + e.pageY - lastPoint.y
$('.dialog').css("left",targetX+'px')
$('.dialog').css("top",targetY+'px')
lastPoint.x = e.pageX
lastPoint.y = e.pageY
}
}).on("mouseup",function () {
isMouseDown = false;
lastPoint = {}
})
</script>
</body>
</html>
二、HTML5方式:
在HTML5中,拖放事件由不同的元素产生,一个元素被拖放,他可能会经过很多个元素上,最终到达想要放置的元素内,这里把被拖放的元素称为源对象,被经过的元素称为过程对象,到达的元素称为目标对象,不同的对象产生不同的拖放事件。
(一)源对象事件:
- dragstart:源对象开始拖放,开始移动被拖拽元素时触发(主体是被拖拽元素)
- drag:源对象拖放过程中,移动被拖拽元素时触发(主体是被拖拽元素)
- dragend:源对象拖放结束,整个拖放操作结束时触发(主体是被拖拽元素)
(二)过程对象事件:
- dragenter:源对象开始进入过程对象范围内,被拖拽元素进入目标元素时触发(主体
是目标元素) - dragover:源对象在过程对象范围内移动,被拖拽元素在目标元素内移动时触发(主
体是目标元素) - dragleave:源对象离开过程对象的范围,被拖拽元素离开目标元素时触发(主体是目
标元素)
(三)目标对象事件:
- drop:源对象被拖放到目标对象内,目标元素完全接受被拖拽元素时触发(主体是目
标元素)
三、HTML5拖放的数据传递对象
在所有拖放事件中提供了一个数据传递对象
dataTransfer
,用于在源对象和目标对象间传递数据。它包含了一些方法及属性。包括了setData()
、getData()
、clearData()
方法来操作拖拽过程中传递的数据,setDragImage()
方法来设置拖拽时鼠标的下面的图片(默认为被拖拽元素),effectAllowed 和 dropEffect 属性来设置拖放效果。
(一)setData(format,data)
:
设置拖拽事件中传递的数据,format 参数为数据类型该方法向 dataTransfer 对象中存入数据,接收两个参数,第一个表示要存入数据种类的字符串,现在支持有以下几种:
- text/xml:XML 文字
- text/uri-list:URL 列表,每个 URL 为一行
第二个data参数是要存入的数据,如:
event.dataTransfer.setData('text/plain','Hello World');
(二)getData(format)
:
- 获拖拽事件中传递的数据,format 参数为数据类型
- 该方法从 dataTransfer 对象中读取数据,参数为在 setData 中指定的数据种类,例
如:event.dataTransfer.getData('text/plain');
(三)clearData()
:
该方法清除 dataTransfer 对象中存放的数据,参数可选,为数据种类。若参数为空,
则清空所有种类的数据
(四)setDragImage(element, x, y)
:
该方法通过用 img 元素来设置拖放图标,其中 element 表示拖拽时鼠标下面的图片,x 表示图标距离鼠标指针的 x 轴方向的偏移值,y 表示图标距离鼠标指针 y 轴方向的偏移值,例如:
var source = document.getElementById('source'),
icon = document.createElement('img');
icon.src = 'img.png';
(五)files属性:
返回被拖拽的 FileList(文件列表),相当于它是用户拖拽进浏览器的文件列表,是个FileList对象,有length
属性,可以通过下标访问
四、HTML5拖放演示demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用拖拽更改支付宝的默认付款方式</title>
<style type="text/css">
h3{
width:310px;
height:20px;
position:absolute;
left:50%;
margin-left:-115px;
font-family:"黑体";
}
ul{
list-style:none;
position:absolute;
left:50%;
top:50px;
margin-left:-150px;
width:300px;
height:300px;
}
li{
box-sizing:border-box;
padding:10px 0 10px 0;
border:1px dashed gray;
}
</style>
</head>
<body>
<h3>使用拖拽更改支付宝的默认付款方式</h3>
<ul id="card">
<li draggable="true">招商信用卡</li>
<li draggable="true">交通信用卡</li>
<li draggable="true">中信储蓄卡</li>
<li draggable="true">建行储蓄卡</li>
<li draggable="true">蚂蚁花呗</li>
<li draggable="true">余额宝</li>
<li draggable="true">余额</li>
</ul>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script>
$(function(){
var dragSrc;
$('li').each(function(index,ele){
$(ele).on("dragstart",function(e){
dragSrc = this;
e.originalEvent.dataTransfer.setData("text/html",this.innerHTML)
}).on("dragover",function(e){
e.preventDefault();
}).on("drop",function(e){
if(dragSrc!=this){
dragSrc.innerHTML = this.innerHTML;
this.innerHTML = e.originalEvent.dataTransfer.getData("text/html")
}
})
})
})
</script>
</body>
</html>