基于JavaScript 实现拖放功能


Posted in Javascript onSeptember 12, 2019

HTML 的拖放 API 依赖 DOM 事件模型,获取拖放和放置元素的相关信息,以此实现拖放功能。我们只需要注册很少几个事件监听器,就能把任何元素变成可拖动或可放置的。

拖放 API 除了提供基本的拖放功能接口外,还可以在拖放之外提供选择,用来自定义行为。比如,可以修改拖放元素的 CSS 样式。或者,我们不移动元素,拖动的时候,复制一个副本,拖放结束后,我们就会多了一个同样的元素。

本篇只介绍实现基本的拖放功能。

将元素设置成可拖动的

我们先从拖动元素开始。假设我们有一个容器元素,其中包含两种类型的子元素:可拖动元素和可放置元素。举个例子,如果我们有一个待办事项列表,我们可以将待办事项拖到“完成”区域。

简单起见,我们将移动的元素称为拖动元素,将拖动元素移入的目标元素称为 dropzone。

<div class='parent'>
 <span id='draggableSpan'>
  draggable
 </span>
 <span> dropzone </span>
</div>

基于JavaScript 实现拖放功能

这是我们的第一段代码,子元素现在还 不能 拖动。

下面给拖动元素添加属性 draggable='true' ,将它设置成一个可拖动元素。

<div class='parent'>
 <span id='draggableSpan' draggable='true'>
  draggable
 </span>
 <span> dropzone </span>
</div>

基于JavaScript 实现拖放功能

现在你再用鼠标拖动拖动元素的时候,它就会跟随鼠标移动(对不起,移动端不行:see_no_evil:)。

draggable 属性在没设置的情况下,默认值 auto 。就是说,元素是可不可以拖动,取决于浏览器的默认设置。比如,链接( <a> )默认就是可拖动的,而 <span> 就不是。

拖放事件处理器

到目前为止,如果我们拖动元素,释放鼠标,什么事都不会发生。拖动和放置都会触发事件,实现一个基本的拖放功能,我们最少需要用到拖放 API 中的三个事件:

ondragstart
ondragover
ondrop

学会使用 ondragstartondragoverondrop 事件只是个开始。拖拽过程一共会涉及八个事件: ondragondragendondragenterondragexitondragleaveondragoverondragstartondrop

DataTransfer

DataTransfer 接口中保存了与当前拖放过程相关的跟踪信息,信息从 DataTransfer 对象属性中获得,而 DataTransfer 对象又是从 DOM 事件对象中获得的。

技术上讲, DataTransfer 接口可以同时跟踪多个拖动对象的信息,我们这里只关注拖动一个元素的情况。:sparkles:

拖动时更新元素

下一步,我们开始设置 ondragstart 的事件处理器。

拖动开始时,我们可以在 ondragstart 处理器中,做任何想做的修改。比如更新拖动元素的 CSS 样式,将拖动的版本设置为临时图片,或者其他能从 DOM 事件中访问到的任何内容。

dataTransfer 对象的 setData 属性可以用来设置拖动状态信息。它接收两个参数,第一个参数是表示内容格式的字符串,第二个参数是实际传递的数据。

我们要实现的功能是将拖动元素移动到一个新的父元素里面。我们需要获取拖动元素,因此需要将拖动元素的 ID 通过 setData 属性保存下来:

function onDragStart(event) {
 event
  .dataTransfer
  .setData('text/plain', event.target.id);
}

再从事件对象中获得拖动元素并设置 CSS 样式:

function onDragStart(event) {
 event
  .dataTransfer
  .setData('text/plain', event.target.id);

 event
  .currentTarget
  .style
  .backgroundColor = 'yellow';
}

注意:如果上面的黄色背景样式,你只希望在拖动时才应用,那么拖动结束后,就要手动将样式恢复。就会说,拖动开始时,如果修改了元素样式,除非再次修改过来,否则样式是不会自动恢复的。:rainbow:

拖动开始时的处理函数写好了,现在将它设置给可拖动元素的 ondragstart 属性:

<div class='parent'>
 <span id='draggableSpan'
  draggable='true'
  ondragstart='onDragStart(event);'>
   draggable
 </span>

 <span> dropzone </span>
</div>

下面是使用鼠标拖动时的效果:

基于JavaScript 实现拖放功能

现在拖动元素, ondragstart 中的代码就会执行,样式改变了,但释放拖动元素后,什么事情都没发生。接下来我们将视线转移到 dropzone 上来。

设置元素为可放置的

ondragstart 之后,下一个要写的处理函数就是 ondragover 了。上面讲过,放置行为默认是被浏览器阻止的,我们需要取消这个默认行为,双重否定为肯定,对吧?

function onDragOver(event) {
 event.preventDefault();
}

在阻止浏览器干扰后,现在就能将拖动元素添加到 dropzone 了,dropzone 成为能够接受任何拖动元素的容器元素。

<div class='parent'>
 <span id='draggableSpan'
  draggable='true'
  ondragstart='onDragStart(event);'>
   draggable
 </span>

 <span ondragover='onDragOver(event);'>
  dropzone
 </span>
</div>

即便现在 dropzone 可以接受拖动元素,释放鼠标后还是看不见改变发生。

放置的时候要做什么?

现在要介绍第三个也是最后一个处理函数 ondrop

我们的函数逻辑遵循以下步骤:

  • 还记得在 setData 中设置的数据吗?
  • 现在我们需要从 dataTransfer 对象的 getData 属性中获取设置的数据,数据内容是拖动元素的 ID,它会返回给我们。
  • 使用上一步获取的 ID,获得拖动元素。 获取 dropzone 元素。
  • 将拖拽元素 append 到 dropzone 中。
  • 清理 dataTransfer 对象中保存的数据。
function onDrop(event) {
 const id = event
  .dataTransfer
  .getData('text');

 const draggableElement = document.getElementById(id);
 const dropzone = event.target;
 
 dropzone.appendChild(draggableElement);

 event
  .dataTransfer
  .clearData();
}

因为这是我们要写的第三个也是最后一个函数,我们只要将它传递给 dropzone 的 ondrop 属性,就完成了一个完整的拖放功能!

<div class='parent'>
 <span id='draggableSpan'
  draggable='true'
  ondragstart='onDragStart(event);'>
   draggable
 </span>

 <span
  ondragover='onDragOver(event);'
  ondrop='onDrop(event);'>
   dropzone
 </span>
</div>

基于JavaScript 实现拖放功能

这里写的示例是最基本的,它展示如何使页面上的任何内容可变得可拖动。当然,一个网页里可以同时包含多个可拖动元素、多个 dropzone,或者使用文本没有介绍的其他事件做更加细粒度的自定义设置。

下面展示的是本文一开始提到的那个简单的待办事项列表功能。:fire:

基于JavaScript 实现拖放功能

只要依据本文上面已经讲过的内容,稍微变通一下,就能写出来。只要确保这里可拖动待办项目的 ID 是唯一的就行了。

总结

以上所述是小编给大家介绍的基于JavaScript 实现拖放功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
javascript应用:Iframe自适应其加载的内容高度
Apr 10 Javascript
浅析js封装和作用域
Jul 09 Javascript
解析URI与URL之间的区别与联系
Nov 22 Javascript
js禁止回车提交表单的示例代码
Dec 23 Javascript
jQuery手机浏览器中拖拽动作的艰难性分析
Feb 04 Javascript
JS模仿编辑器实时改变文本框宽度和高度大小的方法
Aug 17 Javascript
JavaScript生成带有缩进的表格代码
Jun 15 Javascript
JS禁止查看网页源代码的实现方法
Oct 12 Javascript
利用Node.js编写跨平台的spawn语句详解
Feb 12 Javascript
jQuery实现手机号正则验证输入及自动填充空格功能
Jan 02 jQuery
jQuery实现的电子时钟效果完整示例
Apr 28 jQuery
解决element-ui里的下拉多选框 el-select 时,默认值不可删除问题
Aug 14 Javascript
Node.JS用纯JavaScript生成图片或滑块式验证码功能
Sep 12 #Javascript
layui 对table中的数据进行转义的实例
Sep 12 #Javascript
layui点击数据表格添加或删除一行的例子
Sep 12 #Javascript
小程序如何支持使用 async/await详解
Sep 12 #Javascript
layui清空,重置表单数据的实例
Sep 12 #Javascript
layui table 多行删除(id获取)的方法
Sep 12 #Javascript
详解Vue中CSS样式穿透问题
Sep 12 #Javascript
You might like
PHP 中检查或过滤IP地址的实现代码
2011/11/27 PHP
PHP实现连接设备、通讯和发送命令的方法
2015/10/13 PHP
PHP面向对象继承用法详解(优化与减少代码重复)
2016/12/02 PHP
javascript小组件 原生table排序表格脚本(兼容ie firefox opera chrome)
2012/07/25 Javascript
基于jQuery的简单九宫格实现代码
2012/08/09 Javascript
Javascript自定义排序 node运行 实例
2013/06/05 Javascript
node.js中的http.get方法使用说明
2014/12/14 Javascript
jQuery中DOM树操作之复制元素的方法
2015/01/23 Javascript
举例详解Python中smtplib模块处理电子邮件的使用
2015/06/24 Javascript
使用JS实现图片展示瀑布流效果(简单实例)
2016/09/06 Javascript
bootstrap为水平排列的表单和内联表单设置可选的图标
2017/02/15 Javascript
基于dataset的使用和图片延时加载的实现方法
2017/12/11 Javascript
javascript中innerHTML 获取或替换html内容的实现代码
2020/03/17 Javascript
详解Vue中的watch和computed
2020/11/09 Javascript
利用Python3分析sitemap.xml并抓取导出全站链接详解
2017/07/04 Python
Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解
2019/02/28 Python
new_zeros() pytorch版本的转换方式
2020/02/18 Python
Python selenium文件上传下载功能代码实例
2020/04/13 Python
python 中的命名空间,你真的了解吗?
2020/08/19 Python
Python装饰器如何实现修复过程解析
2020/09/05 Python
matplotlib绘制正余弦曲线图的实现
2021/02/22 Python
基于Jquery和Css3代码制作可以缩放的搜索框
2015/11/19 HTML / CSS
加拿大租车网站:Enterprise Rent-A-Car
2018/07/26 全球购物
英国家用电器折扣网站:Electrical Discount UK
2018/09/17 全球购物
俄罗斯美容和健康网上商店:Созвездие Красоты
2019/07/23 全球购物
阿迪达斯英国官方网站:adidas英国
2019/08/13 全球购物
实习期自我鉴定
2013/10/11 职场文书
设计部经理的岗位职责
2013/11/16 职场文书
人民调解员先进事迹材料
2014/05/08 职场文书
2015元旦主持词开场白和结束语
2014/12/14 职场文书
公司介绍信范文
2015/01/31 职场文书
收银员岗位职责
2015/02/03 职场文书
2015年学校信息技术工作总结
2015/05/25 职场文书
远程教育培训心得体会
2016/01/09 职场文书
nginx常用配置conf的示例代码详解
2022/03/21 Servers
SONY600GR,国产收音机厂商永远的痛
2022/04/05 无线电