整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

详解javascript拖拽基础

拽成为一项标准也是近几年的事,属于HTML5中的一部分,作为一种交互行为,拖拽是被广泛应用再界面软件中的,例如桌面应用,word、QQ软件都有拖拽行为。

在HTML5标准实施之前,拖拽也是被广泛使用的,web开发者将click、mouseover,mousemove组合起来实现拖拽逻辑,过程略显冗余和繁琐。

一言蔽之,HTML5的出现让拖拽开发变得简单

先来一张流程图

下图描绘了拖拽的流程.

要点概括总结

结合上图,我们梳理下知识点,做个拆分与解析。

一共有哪些事件

  • 拖: dragstart , drag , dragend
  • 放: dragenter , dragover , dragleave , drop

哪些实体可以被拖

draggable
wordContainerEle.onselectstart = event => false;

这意味着:

  • 元素 默认禁止拖拽 (貌似都是),需要手动设置draggable属性为true。
  • 文字默认都是能选中的,这个大家都习以为常了。

需要说明的是,一个元素被设置draggable之后,里面的文本就无法被选中了(chrome测试如此)。

关于放,有哪些限制?

  • dragenter :都可以。
  • dragover :都可以
  • dragleave :都可以
  • drop :只有在 dragover监听中阻止默认行为 ,才能触发drop

拖放会冒泡嘛?

答案是肯定的。假设一个父元素包含一个子元素,理所当然地,用户拖子元素也是间接的拖动父元素的过程。

近在摸鱼的过程中,发现了一个拖动组件,发现挺有意思的。于是想到在HTML5原生就支持这个功能,于是就想着自己也试着弄一个小demo试试看

提要

最早在网页中引入拖放功能的是IE4。当时,网页中只有两种对象可以拖放,图像和某些文本。拖动图像时,先把鼠标放在图像上,按住鼠标不放就可以拖动它。拖动文本时,要先选中文本,然后就可以想要拖动图像那样拖动。在IE4中,唯一有效的防止目标是文本框,到了IE5,拖放功能添加了新的时间,网页中几乎任意元素都可以作为目标元素。HTML5以IE的实例为基础制订了拖放规范。

案例

  • 一个简单的拖拉

代码

拖动样式

通过div添加draggable属性为true之后,我们已经可以进行简单的拖动了。那么拖动已经是可以拖动了,我们需要另一个地方来接收拖动,所以我们对代码做了些修改
  • 来回拖动案例

来回拖动案例

文字支持在两个框中拖动

需要注意的点

1.需要设置要移动属性draggable的属性值为true才支持拖拽
2.dataTransfer.setData设置了被拖动的数据类型和值
3.dataTransfer.getData("Text") 方法获得被拖的数据。
4.当放置被拖数据时,会发生 drop 事件,调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)。

API

  • 拖动前
draggable元素是否可拖拽
- true 可拖拽
- false 不可拖拽
- auto 跟随浏览器定义是否可以拖拽
  • 绑定在拖拽目标
dragstart()
- 当用户开始拖拽一个元素或者一个文本选取区块的时触发
drag()
- 当用户正在拖拽一个元素或者一个文本选取区块的时触发
dragend()
- 当用户结束拖拽一个元素或者一个文本选取区块的时触发
  • 绑定在放置目标
dragenter	
- 当一个元素或文字选取区块被拖曳移动进入一个有效的放置目标时触发
dragover	
- 当一个元素或文字选取区块被拖曳移动经过一个有效的放置目标时触发
dragleave	
- 当一个元素或文字选取区块被拖曳移动离开一个有效的放置目标时触发
dragexist	
- 当一个元素不再是被选取中的拖曳元素时触发
drop	
-当一个元素或文字选取区块被放置至一个有效的放置目标时触发
  • DataTransfer对象
属性
- types 
只读属性。它返回一个我们在dragstart事件中设置的拖动数据格式的数组。 格式顺序与拖动操作中包含的数据顺序相同。
- files
返回拖动操作中的文件列表。包含一个在数据传输上所有可用的本地文件列表。如果拖动操作不涉及拖动文件,此属性是一个空列表。
- dropEffect
获取当前选定的拖放操作的类型或将操作设置为新类型[none、move、copy、link]
- effectAllowed
指定拖放操作所允许的效果[none, copy, copyLink, copyMove, link, linkMove, move, all, uninitialized]

方法
void setData(format, data)
- 将拖动操作的拖动数据设置为指定的数据和类型。format可以是MIME类型
String getData(format)	
- 返回指定格式的数据,format与setData()中一致
void clearData([format])	
- 删除给定类型的拖动操作的数据。如果给定类型的数据不存在,此方法不执行任何操作。如果不给定参数,则删除所有类型的数据。
void setDragImage(img, x, y)	
- 指定一副图像,当拖动发生时,显示在光标下方。大多数情况下不用设置,因为被拖动的节点被创建成默认图片。x,y参数分别指示图像的水平、垂直偏移量

兼容性

浏览器支持情况

总结

简单几行代码就实现简单拖拽效果,如果不使用原生drop要实现拖拽效果需要比较复杂,兼容性方面的问题也没有特别大的问题(IE除外),相信在今后的工作中会有机会用到。当然在使用过程中也遇到一个问题,当放置被拖数据时,会发生 drop 事件,调用 preventDefault来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开),如果不使用preventDefault,则不会触发drop事件,则拖拽就不会触发。

先,通过视频了解一下我们要实现的效果,视频如下:

<script src="https://lf3-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>

分析

1.点击弹出框,状态框和遮挡层(背景变灰)就会显示出来 display:block;

2.点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;

3.在页面中拖拽的原理:鼠标按下并且移动,之后松开鼠标

4.触发事件是鼠标按下mousedown,鼠标移动mousemove,鼠标松开mouseup

5.推拽过程:鼠标移动过程中,获得最新的值赋给模态框的left和top值,这样模态框就可以跟着鼠标走了

6.鼠标按下出发的事件源是最上面一行,就是id为title

7.鼠标的坐标减去鼠标在盒子内的坐标,才是真正模态框的位置

8.鼠标按下,我们要得到鼠标在盒子的坐标

9.鼠标移动,就让模态框的坐标设置为:鼠标坐标减去盒子坐标即可,注意移动事件写到按下事件里面

10.鼠标松开,就是停止拖拽,就是可以让鼠标移动事件解除

代码