起因

最近在公司打杂的时候,突然分到了一个锅,就是要支持一个新的功能:用户可以通过拖曳组件来改变组件的顺序。因此,这阵子就看了一下网上的一些drag和drog的文章以及W3C的介绍,然后自己亲手实践了一下,毕竟打码,才能变得更强。
首先,先放一个我的demo,大家可以去那里随便拖动一下玩一玩:
https://chenjigeng.github.io/example/drag.html

知识储备

与drag和drog有关的属性和事件

  • draggable属性: 如果你想让一个元素变得可以拖曳的话,那么你就必须设置它的draggable=true,如下
<div class='target' draggable="true"></div>

这样,该元素就可以拖动了

  • ondragstart: 当元素开始被拖动时,触发该事件,目标对象是被拖动的元素
  • ondragover: 当被拖动元素在悬挂元素上移动的时候,该事件触发。目标对象是被拖动元素悬挂的那个元素。
  • ondragleave: 当被拖动元素离开悬挂元素时,触发该事件。目标对象是被拖动元素悬挂的那个元素。
  • ondrop: 当鼠标松开被拖动元素的时候,触发该事件。目标对象是被拖动元素悬挂的那个元素。
  • ondragend: 当鼠标松开被拖动元素的时候,触发该事件。目标对象是被拖动的元素。其中,ondrop事件会先于ondragend事件触发。
  • event.preventDefault: 当触发ondragover事件的时候,必须使用event.preventDefault(),否则的话,ondrop事件就不会触发
  • event.dataTransfer.effectAllowed:设置或返回被拖动元素允许发生的拖动行为。可设置的属性很多,这里我们就不细说,感兴趣的可以去查下,一般来说,我们都设置为"move".

插入节点的方法

  • 将节点插入到另一个节点前面,代码如下
 function insertBefore(insertNode, node) {node.parentNode.insertBefore(insertNode, node)}

这个其实比较简单,就是找到节点的父亲,然后将要插入的节点放到节点的前面。

  • 将节点插入到另一个节点后面,代码如下图
 function insertAfter(insertNode, node) {if (node.nextElementSibling) {insertBefore(insertNode, node.nextElementSibling)} else {node.parentNode.appendChild(insertNode)}}

这个其实也挺简单的,就是如果该节点有兄弟节点的话,那么就将插入节点放到它兄弟节点的前面,否则,则说明该节点是父节点的最后一个节点,因此直接将插入节点放到父节点的末尾。

实践

在这里,我们要做的就是一个支持各个图片拖曳来交换位置的玩意,不过,当图片交换位置的时候,不单单是图片交换位置,而是包含图片的容器交换位置。

1.我们先放置几张图片,并且将它们的dragable设置为true,这样它们就可以拖动了。代码如下:

<body><div class='target' draggable="true"><img src="./imgs/1.jpeg" alt="1"></div><div class='target' draggable="true"><img src='./imgs/2.jpg' /></div><div class='target' draggable="true"><img src="./imgs/3.jpg" alt="ss"></div>    <div class='target' draggable="true"><img src="./imgs/4.jpg" alt="ss"></div>   </body>

效果:

2.为每个div都设置一个ondragstart函数,当该函数触发的时候,进行初始化操作,比如记录当前的目标对象,拖动目标的y值,以及设置拖动的效果。

// 拖动的目标对象
let target = ''
// 拖动的目标对象的y值
let targetOffsetTop = 0
// 当元素开始被拖动时,触发该事件,目标对象是被拖动的元素
function handleDragStart(ev) {target = findTarget(ev.target)targetOffsetTop = ev.target.offsetTopev.dataTransfer.effectAllowed = 'move'
}
// 找到类名为target的目标对象
function findTarget(node) {if (!node || node == document) {return null}if (node.classList.contains('target')) {return node;}return findTarget(node.parentNode)
}

3.为每个div注册一个ondragover事件和ondragleave事件,在ondragover事件里,主要是调用event.preventDefault来防止ondrog不会被触发,并且为了看起来更明显,当ondragover事件触发的时候,为目标对象增加一个dotted类。当ondragleave事件触发的时候,则把dotted类从目标对象移除。

// 当被拖动元素在悬挂元素上移动的时候,该事件触发。目标对象是被拖动元素悬挂的那个元素。
// 必须执行event.preventDefault(),不然的话ondrop不会触发
function handleDragOver(ev) {ev.preventDefault();ev.target.classList.add('dotted')
}
// 当被拖动元素离开悬挂元素时,触发该事件。目标对象是被拖动元素悬挂的那个元素。
function handleDragLeave(ev) {ev.target.classList.remove('dotted')
}

4.为每个div注册ondrog事件和ondragend事件,ondrog事件是重点,它主要是根据被拖动元素和被拖动元素悬挂的那个元素的坐标,来决定是要将被拖动元素插入到悬挂元素的前面还是后面。而ondragend主要是用于将target设置为null,代码如下:

// 当鼠标松开被拖动元素的时候,触发该事件。目标对象是被拖动元素悬挂的那个元素。
function handleDrog(ev) {let resultOffsetTop = ev.target.offsetTopif (targetOffsetTop < resultOffsetTop) {insertAfter(target, findTarget(ev.target))}else {insertBefore(target, findTarget(ev.target))}ev.target.classList.remove('dotted')
}
// 将节点插入到另一个节点前面
function insertBefore(insertNode, node) {node.parentNode.insertBefore(insertNode, node)
}
// 将节点插入到另一个节点后面
function insertAfter(insertNode, node) {if (node.nextElementSibling) {insertBefore(insertNode, node.nextElementSibling)} else {node.parentNode.appendChild(insertNode)}
}
// 当松开鼠标的时候,触发该事件。目标对象是被拖动的对象
function handleDragEnd(ev) {target = null
}

这样子,我们就实现了一个可以通过拖曳来改变图片顺序的一个小玩意啦~完整的代码放到https://github.com/chenjigeng/something 上了~有兴趣的可以git clone下来跑一跑

本文地址在->本人博客地址, 欢迎给个 start 或 follow

HTML5 drag和drop的亲手实践相关推荐

  1. html拖放数据库字段,HTML5 拖放(Drag 和 Drop)

    拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. #div1 {width:350px;height:70px;padding:10p ...

  2. HTML5 drag drop 拖拽与拖放简介

    by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=1419 一.前面的话 ...

  3. html组态图动态拖拽,基于HTML5的Drag and Drop生成图片Base64信息

    HTML5的Drag and Drop是很不错的功能,网上使用例子较多如 http://html5demos.com/drag ,但这些例子大部分没实际用途,本文将搞个有点使用价值的例子,通过Drag ...

  4. html5怎么设置drop,HTML5 拖放(Drag 和 Drop)

    拖放(Drag 和 drop)是 HTML5 标准的组成部分. 将 RUNOOB.COM 图标拖动到矩形框中. 拖放 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标 ...

  5. html5css3菜鸟教程,HTML5+CSS3实现拖放(Drag and Drop)示例

    本文简单介绍一下HTML5的拖放实现.MXGHTML5中文学习网 - HTML5先行者学习网 拖放(Drag 和 drop)是 HTML5 标准的组成部分.MXGHTML5中文学习网 - HTML5先 ...

  6. HTML5 拖放(Drag 和 Drop)简介

    拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. HTML5 拖 ...

  7. 详解Html5关于拖拽(Drag 和 drop)的使用和事件

    拖放(Drag 和 drop)是 HTML5 标准的组成部分.在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 1. 相关事件 drag 拖动元素或选择文本时触发此事件. dragend ...

  8. HTML5 仿QT 示例Drag and Drop Robot 换装机器人

    起源 在Qt的示例中看到了一个有趣的demo,截图如下: 这个demo的名字叫Drag and Drop Robot,简单概括而言,在这个demo中,可以把机器人四周的颜色拖动到机器人的各个部位,比如 ...

  9. 基于html5拖(drag)放(drop)实现换装小游戏

    编码环境:asp.net mvc3  html5 运行环境:firefox浏览器通过. 一:有关html5的拖放功能,网上介绍的一大把,我将自己学习到的知识点总结如下: 1:全局属性draggable ...

最新文章

  1. Java并发编程(十)设计线程安全的类
  2. TCP、UDP和HTTP
  3. 转:ORACLE的JDBC连接方式:OCI和THIN
  4. LeetCode:二进制手表【401】
  5. 网站的服务器分哪几种,服务器有哪几种分类?_服务器可分为四种类型
  6. ajax回调函数有时成功有时失败,javascript - Ajax 回调函数行为随机。我做错了什么?...
  7. LeetCode50. Pow(x, n)(二进制位运算)
  8. SpringBoot SSM 心理咨询论坛社区
  9. zabbix 添加jvm监控
  10. 【Axure原型分享】评论元件
  11. Ubuntu软件商店下载速度慢
  12. 我国国防是全军的国防_国防部长
  13. 硫化仪硫化反应诱导、交联反应和网状结构形成
  14. appdata是什么文件夹?appdata文件夹可以删除吗?
  15. linux bison 手册
  16. 用Python的Seaborn库绘制17个超好看图表
  17. Ceph PG 归置组状态
  18. 优秀的加密方案-软件加密技巧
  19. R3DS Wrap基本使用方法
  20. 实用工具—SimpleMind 和Sublime Text

热门文章

  1. python conda安装
  2. 数组的归一化c语言,如何归一化频率数组
  3. STM32F411 Discovery学习笔记(四)串口
  4. SLMi334兼容TLP5214 一款兼容光耦带保护功能单通道隔离IGBT栅极驱动器
  5. matlab绘制散点拟合图
  6. java 搞笑翻译_那些让我们哭笑不得的爆笑翻译!佩服网友的脑洞!
  7. 2022国自然中标至少1篇1区代表作?没中接下来怎么办?
  8. 冰箱中的爱马仕没跑了,用COLMO来开启你的美好新春吧
  9. javaweb超市管理系统--用户管理
  10. Android S 新特性:应用行为更改