其实HTML5就是新增一些有用的API
让我们更轻松的开发
从而把更多精力都放在业务逻辑上来
这些API的使用也非常简单
不过我的记性不太好
所以还是以博客的形式记录下来(手动滑稽)
今天就来写一下这个拖拽API
默认拖拽
说起拖放,其实最早实现拖放功能的还是IE(IE4)
H5就是在IE实例的基础上指定的拖拽规范
在浏览器中,是有默认拖拽的
比如说图片的拖拽
选中文本的拖拽
链接的拖拽
元素拖拽
浏览器默认允许我们拖拽图像、文本以及链接
让其它元素被拖动也是可以实现的
只需要在元素标签上添加一个属性
<div draggable="true"></div>
当拖拽这个元素的时候,浏览器就会以半透明复本的方式显示
拖拽事件
拖拽事件应该分为两类
一类是被拖拽元素触发的事件
另一类是拖放目标元素触发的事件
<div id="source" draggable="true"></div>
<div id="target"></div> <!-- 样式略 -->
var source = document.getElementById('source');
var target = document.getElementById('target');
拖拽元素
拖拽元素的时候,被拖拽元素会触发以下事件
- dragstart
- drag
- dragend
当鼠标点中元素并且开始移动时,就会触发dragstart事件(类比mousedown)
拖拽过程中会持续不断地触发drag事件(类比mousemove)
松开鼠标取消拖拽时就会触发dragend事件(类比mouseup)
source.ondragstart = function(){
console.log('开始拖拽');
}
source.ondrag = function(){
console.log('拖拽中');
}
source.ondragend = function(){
console.log('拖拽结束');
}
目标元素
当拖拽的元素拖到一个目标元素上时,目标元素会触发以下事件
- dragenter
- dragover
- dragleave
- drop
拖拽元素到目标上,就会触发dragenter事件(类比mouseover)
当拖动元素在目标元素中,就会持续触发dragover事件
离开目标元素,触发dragleave事件(类比mouseout)
若拖放元素到了目标元素中(在目标元素中松开鼠标),就会触发drop事件而不会触发dragleave事件
target.ondragenter = function(){
console.log('拖动进入目标元素');
}
target.ondragover = function(){
console.log('目标元素中拖拽');
}
target.ondragleave = function(){
console.log('拖动离开目标元素');
}
target.ondrop = function(){
console.log('拖放');
}
这时我们会发现元素拖放到目标元素中时
并没有触发drop事件
我们看到了一个特殊的光标(圆环+反斜线)
意思就是无效的拖放
所以导致没有触发drop事件
也就是说元素默认是不能够拖放
只要我们在目标元素的dragover事件中取消默认事件就可以解决问题
target.ondragover = function(e){
console.log('目标元素中拖拽');
e.preventDefault(); //增
}
数据交换
只是简单的拖放毫无意义
我们需要进行数据交换
而这个用语数据交换的对象就是事件对象的属性dataTransfer
dataTransfer的两个核心方法是setData()和getData()
setData()用于设置数据,getData()用语接收数据
event.dataTransfer.setData('text','some text');
var text = event.dataTransfer.getData('text');
//保存在dataTransfer中的数据只能在drop事件处理函数中处理
如果我们拖拽了选中文本
那么浏览器默认就会调用dataTransfer.setData,设置对应文本数据
setData()和getData()就是数据类型的字符串
IE定义的数据类型除了“text”文本类型还有“URL”
H5对它进行了扩展,可以指定各种MIME类型
但为了向后兼容,它同样支持“text”和“URL”
它们会被分别映射为“text/plain”和“text/uri-list”
如果数据保存为URL,浏览器会做特殊处理,把它当成网页链接
(所以拖拽链接到另外的浏览器窗口就会打开网页)
必要的话,我们可以手动保存需要传输的数据
var source = document.getElementById('source');
var target = document.getElementById('target');
source.ondragstart = function(e){
e.dataTransfer.setData('text','传递文本数据');
}
target.ondragover = function(e){
e.preventDefault();
}
target.ondrop = function(e){
console.log(e.dataTransfer.getData('text'));
}
拖拽设置
在dataTransfer中还有两个重要的属性
dropEffect和effectAllowed
dropEffect
dropEffect属性值为字符串,表示被拖动元素可以执行哪一种放置行为
要使用这个属性,必须在dragenter事件处理函数中设置
- none 不能把元素拖放至此(除文本框外全部元素的默认值)
- move 移动到目标
- copy 复制到目标
- link 目标打开拖动元素(拖动元素必须是链接并有URL)
effectAllowed
effectAllowed属性值也是字符串,表示允许拖动元素哪种dropEffect
要使用这个属性,必须在dragst事件处理函数中设置
- uninitialized 没有设置任何拖放行为
- none 不能由任何行为
- copy 仅允许dropEffect值为copy
- link 仅允许dropEffect值为link
- move 仅允许dropEffect值为move
- copyLink 允许dropEffect值为copy和link
- copyMove 允许dropEffect值为copy和move
- linkMove 允许dropEffect值为link和move
- all 允许任意dropEffect
拖拽案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>张高伟拖放api</title> <style> #mydiv{ width: 200px; height: 200px; border: 1px solid indianred; background-color: #5c2699; } #target{ width: 500px; height: 500px; border: 1px solid indianred; background-color: #c0c0c0; } .item{ background-color: cadetblue; border: 1px solid cornsilk; } </style> </head> <body> <!--<div id="mydiv" draggable="true"></div>--> <!--<div id="target" draggable="true"></div>--> <ul class="parent_url"> <li draggable="true" class="item">张高伟</li> <li draggable="true" class="item">李翠翠</li> <li draggable="true" class="item">王三</li> <li draggable="true" class="item">赵武</li> <li draggable="true" class="item">李四</li> </ul> </html> <script> // var source=document.getElementById('mydiv'); // var target=document.getElementById('target'); // // source.ondragstart = function(){ // console.log('开始拖拽'); // } // source.ondrag = function(){ // console.log('拖拽中'); // } // source.ondragend = function(){ // console.log('拖拽结束'); // } // // target.ondragenter = function(){ console.log('拖动进入目标元素'); } // target.ondragover = function(){ // console.log('目标元素中拖拽'); // return false; // } target.ondragleave = function(){ console.log('拖动离开目标元素'); } // target.ondrop = function(){ // console.log('拖放'); // this.appendChild(source) // } //遍历节点 var item=document.getElementsByClassName('item'); //父级 var parent_url=document.getElementsByClassName('parent_url'); for(var i=0,len=item.length;i<len;i++){ //设置ID方便取 item[i].id='mydiv'+i; //每个拖放 item[i].ondragstart = function(e){ //存储id e.dataTransfer.setData('id',this.id) }; //放之前取消默认事件 item[i].ondragover = function(){ return false; }; //放事件 item[i].ondrop = function(e){ //去除拖放开始的ID //console.log(e.dataTransfer.getData('id')) //放到的位置 console.log(this) var tuo_id=e.dataTransfer.getData('id'); var tuo=document.getElementById(tuo_id); //使用insertBefore 达到换位置效果 parent_url[0].insertBefore(tuo,this) this.style.borderTop="2px solid cornsilk" } //拖放中 item[i].ondragenter = function(){ this.style.borderTop="2px solid black" } //离开 item[i].ondragleave = function(){ this.style.borderTop="2px solid cornsilk" } } </script> 拖拽图片<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>张高伟拖放api</title> <style> #mydiv{ width: 200px; height: 200px; border: 1px solid indianred; background-color: #5c2699; } #target{ width: 500px; height: 500px; border: 1px solid indianred; background-color: #c0c0c0; } .item{ background-color: cadetblue; border: 1px solid cornsilk; } </style> </head> <body> <!--<div id="mydiv" draggable="true"></div>--> <!--<div id="target" draggable="true"></div>--> <!--<ul class="parent_url">--> <!--<li draggable="true" class="item">张高伟</li>--> <!--<li draggable="true" class="item">李翠翠</li>--> <!--<li draggable="true" class="item">王三</li>--> <!--<li draggable="true" class="item">赵武</li>--> <!--<li draggable="true" class="item">李四</li>--> <!--</ul>--> </html> <script> // var source=document.getElementById('mydiv'); // var target=document.getElementById('target'); // // source.ondragstart = function(){ // console.log('开始拖拽'); // } // source.ondrag = function(){ // console.log('拖拽中'); // } // source.ondragend = function(){ // console.log('拖拽结束'); // } // // target.ondragenter = function(){ console.log('拖动进入目标元素'); } // target.ondragover = function(){ // console.log('目标元素中拖拽'); // return false; // } target.ondragleave = function(){ console.log('拖动离开目标元素'); } // target.ondrop = function(){ // console.log('拖放'); // this.appendChild(source) // } // //遍历节点 // var item=document.getElementsByClassName('item'); // //父级 // var parent_url=document.getElementsByClassName('parent_url'); // // for(var i=0,len=item.length;i<len;i++){ // //设置ID方便取 // item[i].id='mydiv'+i; // //每个拖放 // item[i].ondragstart = function(e){ // //存储id // e.dataTransfer.setData('id',this.id) // }; // //放之前取消默认事件 // item[i].ondragover = function(){ // return false; // }; // //放事件 // item[i].ondrop = function(e){ // //去除拖放开始的ID // //console.log(e.dataTransfer.getData('id')) // //放到的位置 // console.log(this) // var tuo_id=e.dataTransfer.getData('id'); // var tuo=document.getElementById(tuo_id); // //使用insertBefore 达到换位置效果 // parent_url[0].insertBefore(tuo,this) // this.style.borderTop="2px solid cornsilk" // // } // // //拖放中 // item[i].ondragenter = function(){ // this.style.borderTop="2px solid black" // } // // //离开 // item[i].ondragleave = function(){ // this.style.borderTop="2px solid cornsilk" // } // } //获取整个html var html=document.documentElement; //放之前取消默认事件 html.ondragover = function(){ return false; }; html.ondrop = function(e){ //禁止图片新链接打开 e.preventDefault(); //表示文件 // console.log(e.dataTransfer.files) //图片 console.log(e.dataTransfer.files[0]) if(e.dataTransfer.files[0].type.indexOf('image')==-1){ alert('格式错误') return false; } //创建图像 var image=new Image(); //获取图片路径 image.src=window.URL.createObjectURL(e.dataTransfer.files[0]) image.style.top=e.pageY+'px' image.style.left=e.pageX+'px' image.style.height='200px' image.style.width='200px' // console.log(e.pageY) // console.log(e.pageX) //设置class名字 image.className=''; //将图片添加进去 document.body.appendChild(image) } </script>