HTML5逐步分析实现拖放功能的方法


Posted in HTML / CSS onSeptember 30, 2020

一、什么是拖放

拖放就是通过鼠标放在一个物体上,按住鼠标不放就可以把一个物体托动到另一个位置。其实我们平时一直都有接触,如图

HTML5逐步分析实现拖放功能的方法

那么在网页上其实也可以实现同样效果的拖放功能,如图

HTML5逐步分析实现拖放功能的方法

那么,就让我们来看看如何实现的吧

二、拖放事件

在IE4的时候,Js就可以实现拖放功能了,当时只支持拖放图像和一些文本。后来随着IE版本的更新,拖放事件也在慢慢完善,HTML5就以IE的拖放功能制定了该规范,Firefox 3.5、Safari 3+、chrome以及它们之后的版本都支持了该功能。

默认情况下,网页中的图像、链接和文本是可以拖动的,而其余的元素若想要被拖动,必须将 draggable 属性设置为 true,这是HTML5规定的新属性,用于设置元素是否能被拖动。因此,图像、链接、文本的 draggable 属性默认为 true,其余元素的 draggable 属性默认为 false

在实现拖放功能时有这样两个概念,分别是被拖动元素目标元素,它们都有各自支持的事件,那么我们来了解一下

(1)被拖动元素的事件

被拖动元素所支持的事件如下表所示 

事件 含义
dragstart 准备拖动被拖动元素时触发
drag 拖动的过程中触发(频繁触发)
dragend 拖动结束时触发

我们来用一个例子测试一下这三个事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 100px;
            height: 100px;
            background-color: lightgreen;
        }
    </style>
</head>
<body>
    <div  draggable='true'></div>
    <script>
        let box = document.querySelector('.box')
        // 绑定dragstart事件
        box.addEventListener('dragstart', function() {
            console.log('拖拽开始了');
        })
        // 绑定drag事件
        box.addEventListener('drag', function() {
            console.log('元素被拖动');
        })
        // 绑定dragend事件
        box.addEventListener('dragend', function() {
            console.log('拖拽结束');
        })
    </script>
</body>
</html>

我们来看看测试效果

HTML5逐步分析实现拖放功能的方法

(2)目标元素的事件

在实现拖放功能的过程中,目标元素上的事件有如下三个

 
事件 含义
dragenter 被拖放元素进入目标元素时触发
dragover 被拖放元素在目标元素内时触发(频繁触发)
dragleave 被拖动元素离开目标元素时触发
drop 当被拖动元素被放到了目标元素中时触发

这里我要详细讲解一下这三个事件的触发规则:

  • dragenter事件mouseover 事件类似,那怎样才算被拖放元素进入目标元素呢?经过测试发现,当被拖放元素的一半以上面积在目标元素内才算进入了目标元素
  • dragover事件比较特殊,当拖放元素进入目标元素以后就会一直触发,就跟你设置了一个无限循环的定时器一样,即使你不移动元素也会触发,除非拖放事件结束或者被拖放元素离开目标元素
  • dragleave事件 的其触发条件正好与 dragenter 事件相反,它是当被拖放元素离开目标元素时触发,经过测试,离开目标元素的条件是:被拖放元素一半以上的面积离开目标元素
  • drop事件 可以叫做放置目标事件,它是当被拖放元素放置到了目标元素中时触发。虽然任何元素都支持该事件,但是所有元素默认都是不允许被放置的,所以在不做任何处理的情况下,该事件是不会触发的

同样的,我们来用具体的例子,先来体会一下前三个事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 100px;
            height: 100px;
            background-color: lightgreen;
        }
        .location{
            width: 100px;
            height: 100px;
            background-color: lightpink;
        }
    </style>
</head>
<body>
    <div  draggable='true'></div>
    <div ></div>
    <script>
        let located = document.querySelector('.location')
        // 绑定dragenter事件
        located.addEventListener('dragenter', function() {
            console.log('元素进入了目标元素');
        })
        // 绑定dragover事件
        located.addEventListener('dragover', function() {
            console.log('元素在目标元素内');
        })
        // 绑定dragleave事件
        located.addEventListener('dragleave', function() {
            console.log('元素离开了目标元素');
        })
    </script>
</body>
</html>

我们来看看测试效果,这里你们要仔细看被拖放元素多少面积进入或离开目标元素时才触发的对应事件

HTML5逐步分析实现拖放功能的方法

那么最后我们再来将一下如何才能触发 drop事件,只需要阻止 dragenter事件dragover事件 的默认行为即可。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 100px;
            height: 100px;
            background-color: lightgreen;
        }
        .location{
            width: 100px;
            height: 100px;
            background-color: lightpink;
        }
    </style>
</head>
<body>
    <div  draggable='true'></div>
    <div ></div>
    <script>
        let located = document.querySelector('.location')
        located.addEventListener('dragenter', function(e) {
            e.preventDefault()
        })
        located.addEventListener('dragover', function(e) {
            e.preventDefault()
        })
        located.addEventListener('drop', function() {
            console.log('元素被放置');
        })
    </script>
</body>
</html>

来看下测试效果图

HTML5逐步分析实现拖放功能的方法

值得注意的是,在我们没有对 drop事件 做处理之前,将被拖放元素拖动到目标元素中时,鼠标样式会变成禁止的样式,如图

HTML5逐步分析实现拖放功能的方法

而当我们设置元素为可放置了以后,鼠标样式是这样的。如图

HTML5逐步分析实现拖放功能的方法

三、dataTransfer对象

上面只是简简单单地实现了拖放功能,但并没用利用该功能做出什么实际性的功能,这里我们介绍一个拖放事件中事件对象上的一个特别重要的属性——dataTransfer

我们通过 event.dataTransfer 来获取该对象,其主要的作用就是从被拖放元素向目标元素传递一个字符串数据

(1)方法

dataTransfer上有两个方法,如下表所示

 
方法 含义
setData 设置字符串,并设置数据类型
getData 获取对应数据类型的字符串

setData() 方法接收两个参数,第一个参数表示的是字符串的数据类型,HTML5规定了两种数据类型,分别是 text/plaintext/uri-list,前者表示普通字符串,后者表示URL字符串;第二个参数 就是用于存放的字符串

getData() 方法只接收一个参数,即需要接收的字符串类型

我们来简单使用一下这两个方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 100px;
            height: 100px;
            background-color: lightgreen;
        }
        .location{
            width: 100px;
            height: 100px;
            background-color: lightpink;
        }
    </style>
</head>
<body>
    <div  draggable='true'></div>
    <div ></div>
    <script>
		let box = document.querySelector('.box')
		// 为被拖放元素绑定 dragstart 事件
        box.addEventListener('dragstart', function(e) {
        	// 设置类型为 text/plain 的 字符串
            e.dataTransfer.setData('text/plain', '我是拖放开始时被设置的字符串')
        })

        let located = document.querySelector('.location')
        
        located.addEventListener('dragenter', function(e) {
            e.preventDefault()
        })
        located.addEventListener('dragover', function(e) {
            e.preventDefault()
        })
        located.addEventListener('drop', function(e) {
        	// 将被拖放元素放置到目标元素时获取字符串
            let res = e.dataTransfer.getData('text/plain')
            console.log(res);
        })
    </script>
</body>
</html>

来看下测试结果

HTML5逐步分析实现拖放功能的方法

(2)属性

dataTransfer对象 上还有两个比较常用的属性,如下表所示

 
属性 含义
dropEffect 被拖放元素的放置行为
effectAllowed 目标元素支持的放置行为

首先说一下,这个两个属性需要搭配使用,它们决定了被拖放元素目标元素 之间的关系的,当设定好两者的关系后,在进行拖动操作的时候,鼠标会根据不同的关系显示不同的样式,除此之外,没有别的特别的作用。

dropEffect 可以设置以下几个属性

 
含义
none 默认值。不能把拖动的元素放在这里
move 应该把拖动的元素移动到该目标元素
copy 应该把拖动元素复制到该目标元素
link 表示目标元素会打开被拖放进来的元素对应的链接

【注意】:dropEffect 属性必须在 dragenter事件 中设置,否则无效

effectAllowed 可以设置以下几个属性

含义
uninitialized 被拖放元素没有设置放置性为
none 被拖放元素不能有放置性为
copy 只允许值为 ‘copy’ 的 dropEffect 目标元素
link 只允许值为 ‘link’ 的 dropEffect 目标元素
move 只允许值为 ‘move’ 的 dropEffect 目标元素
copyLink 只允许值为 ‘copy’ 和 ‘link’ 的 dropEffect 目标元素
copymove 只允许值为 ‘copy’ 和 ‘move’ 的 dropEffect 目标元素
linkMove 只允许值为 ‘link’ 和 ‘move’ 的 dropEffect 目标元素
all 只允许任意值的 dropEffect 目标元素

【注意】:effectAllowed 属性必须在 dragstart事件 中设置,否则无效

上面也说了,这两个属性基本上只是用来改变鼠标样式的,所以如果想实现特定的功能还得我们自己来重写事件的处理函数。

下面来看一个拖放实例:

需求: 将一段文本拖放到一个元素中

因为文本是默认支持的拖放元素,所以我们可以不对其做任何的事件绑定。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .location{
            width: 100px;
            height: 100px;
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <div class="box">我是一段测试文字</div>
    <div class="location"></div>
    <script>    
        let located = document.querySelector('.location')

        located.addEventListener('dragenter', function(e) {
            e.dataTransfer.dropEffect = 'copy'
            e.preventDefault()
        })
        located.addEventListener('dragover', function(e) {
            e.preventDefault()
        })
        located.addEventListener('drop', function(e) {
            e.target.innerHTML = e.dataTransfer.getData('text/plain')
        })
    </script>
</body>
</html>

测试动图

HTML5逐步分析实现拖放功能的方法

四、结束语

到此这篇关于HTML5逐步分析实现拖放功能的方法的文章就介绍到这了,更多相关HTML5拖放功能内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

HTML / CSS 相关文章推荐
CSS3 三维变形实现立体方块特效源码
Dec 15 HTML / CSS
基于CSS3实现图片模糊过滤效果
Nov 19 HTML / CSS
CSS3圆角和渐变2种常用功能详解
Jan 06 HTML / CSS
基于DOM+CSS3实现OrgChart组织结构图插件
Mar 02 HTML / CSS
html5 Canvas画图教程(10)—把面拆成线条模拟出圆角矩形
Jan 09 HTML / CSS
高清屏中使用Canvas绘图出现模糊的问题及解决方法
Jun 03 HTML / CSS
使用html2canvas实现将html内容写入到canvas中生成图片
Jan 03 HTML / CSS
用canvas显示验证码的实现
Apr 10 HTML / CSS
video.js支持m3u8格式直播的实现示例
May 20 HTML / CSS
5个HTML5的常用本地存储方式详解与介绍
Mar 27 HTML / CSS
关于CSS自定义属性与前端页面的主题切换问题
Mar 21 HTML / CSS
CSS元素定位之通过元素的标签或者元素的id、class属性定位详解
Sep 23 HTML / CSS
移动端HTML5 input常见问题(小结)
Sep 28 #HTML / CSS
HTML5超文本标记语言的实现方法
Sep 24 #HTML / CSS
Html5 webRTC简单实现视频调用的示例代码
Sep 23 #HTML / CSS
Html5之webcoekt播放JPEG图片流
Sep 22 #HTML / CSS
如何在Canvas上的图形/图像绑定事件监听的实现
Sep 16 #HTML / CSS
canvas 绘图时位置偏离的问题解决
Sep 16 #HTML / CSS
关于canvas.toDataURL 在iOS运行失败的问题解决
Sep 16 #HTML / CSS
You might like
php新建文件自动编号的思路与实现
2011/06/27 PHP
php实现redis数据库指定库号迁移的方法
2015/01/14 PHP
Laravel 5 框架入门(二)构建 Pages 的管理功能
2015/04/09 PHP
php判断用户是否手机访问代码
2015/06/08 PHP
基于PHP实现用户注册登录功能
2016/10/14 PHP
详解将数据从Laravel传送到vue的四种方式
2019/10/16 PHP
php + ajax 实现的写入数据库操作简单示例
2020/05/16 PHP
跨浏览器的设置innerHTML方法
2006/09/18 Javascript
为EasyUI的Tab标签添加右键菜单的方法
2012/07/14 Javascript
ExtJS4中使用mixins实现多继承示例
2013/12/03 Javascript
jQuery+JSON实现AJAX二级联动实例分析
2015/12/18 Javascript
基于iScroll实现下拉刷新和上滑加载效果
2017/07/18 Javascript
vue3.0 CLI - 2.3 - 组件 home.vue 中学习指令和绑定
2018/09/14 Javascript
解决layer弹出层的内容页点击按钮跳转到新的页面问题
2019/09/14 Javascript
bootstrap-table后端分页功能完整实例
2020/06/01 Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
2020/08/07 Javascript
[48:26]VGJ.S vs infamous Supermajor 败者组 BO3 第二场 6.4
2018/06/05 DOTA
Swift中的协议(protocol)学习教程
2016/07/08 Python
基于并发服务器几种实现方法(总结)
2017/12/29 Python
python OpenCV学习笔记直方图反向投影的实现
2018/02/07 Python
Python 实现一行输入多个值的方法
2018/04/21 Python
详解Python if-elif-else知识点
2018/06/11 Python
Django处理多用户类型的方法介绍
2019/05/18 Python
Pandas操作CSV文件的读写实现方法
2019/11/13 Python
python 读取.nii格式图像实例
2020/07/01 Python
python3环境搭建过程(利用Anaconda+pycharm)完整版
2020/08/19 Python
基于python tkinter的点名小程序功能的实例代码
2020/08/22 Python
纯CSS3实现的8种Loading动画效果
2014/07/05 HTML / CSS
介绍一下代理模式(Proxy)
2014/10/17 面试题
QA工程师岗位职责
2013/11/20 职场文书
员工工作表扬信范文
2014/01/13 职场文书
教师党性分析材料
2014/02/04 职场文书
公司聚餐通知
2015/04/22 职场文书
写好求职信的技巧解密
2019/05/14 职场文书
python自动化测试通过日志3分钟定位bug
2021/11/20 Python
世界十大动漫制作公司排行榜,迪士尼上榜,第二是美国代表性文化符
2022/03/18 欧美动漫