H5拖放API基础篇

小雪姑娘_1892

小雪姑娘_1892

2017-05-28

2380人浏览

原创

  不要搞错,本文不是讲如何拖地的。看过《javascript精粹》朋友应该知道,他实现拖放的过程比较复杂,现在时代不同了,我们用h5的新的拖放api就能非常方便的实现拖放效果了。最近在园子见一园友写了一篇《html5 进阶系列:拖放 api 实现拖放排序》,真乃大师之作,大~熊同学作为一代菜鸟(不是宗师),无法与之想比,遂推出基础篇,希望各位园友有所收获。

一、一个简单的例子--地上有石子捡几个吧

  


    地上有石子,捡几个吧
    
    
        
        
        
    
    
    我是篮子    
    
    我是地
    
        石子
        石子
        石子
        石子
        石子
        石子
        石子
        石子
        石子
        石子


  (gif演示是用的edge,我的ubuntu做gif太麻烦了,借了个windows)

  

  这里用一个简单的例子演示了如何实现拖放,那么问题来了,从上面的演示中你可以猜出一些属性和方法的用法了,那些方法的作用究竟是怎样的?那些个属性又是啥意思呢?下面一一到来。

二、实现拖放的一般步骤

  1、找到一个可拖的元素

  正如不是所有人都叫大熊一样,并不是所有的元素都是可以被拖的。img和a元素默认可拖,其他元素默认不可拖,当时可以加一个draggable=true让它可拖。

  


<p></p>


  2、处理拖放有关事件

  所有相关事件如下:(这个摘自:http://www.cnblogs.com/linxin/p/6794542.html)

  源对象:

  • dragstart:源对象开始拖放。

  • drag:源对象拖放过程中。

  • dragend:源对象拖放结束。

  过程对象:

  • dragenter:源对象开始进入过程对象范围内。

  • dragover:源对象在过程对象范围内移动。

  • dragleave:源对象离开过程对象的范围。

  目标对象:

  • drop:源对象被拖放到目标对象内。

  我们可以用一个测试来看看这些事件的触发时机和事件对象为何物。

  


html>
    <meta>
    <title>testEvents</title>
    <style>
        .source{
            width: 50px;
            height: 50px;
            border: 1px solid red;
        }
        .process{
            width: 100px;
            height: 100px;
            border: 1px solid black;
            margin-top: 10px;
        }
        .dest{
            width: 100px;
            height: 100px;
            border: 1px solid green;
            margin-top: 10px;
        }
    </style>
    <p></p>
    <p></p>
    <p></p>
    <script>
    window.onload=function(){        var source = document.getElementById("source");        var process = document.getElementById("process");        var dest = document.getElementById("dest");        var sourceEle;

        source.addEventListener("dragstart",function(e){
            console.log("source dragstart");
            console.log(e);
            sourceEle = e.target;            var dt = e.dataTransfer;
            dt.effectedAllowed = "all";
        },false);

        process.addEventListener("dragenter",function(e){
            console.log("process dragenter");
            console.log(e);
        },false);

        process.addEventListener("dragover",function(e){
            console.log("process dragover");
            console.log(e);
        },false);

        process.addEventListener("dragleave",function(e){
            console.log("process dragleave");
            console.log(e);
        },false);

        source.addEventListener("drag",function(e){
            console.log("source drag");
            console.log(e);
        },false);

        dest.addEventListener("dragend",function(e){
            console.log("dest dragend");
            console.log(e);
            e.preventDefault();
        },false);

        dest.addEventListener("drop",function(e){
            console.log("dest drop");
            console.log(e);
            dest.appendChild(sourceEle);
            e.preventDefault();
            e.stopPropagation();
        },false);

        document.ondragover = function(e){e.preventDefault();}
        document.ondrop = function(e){e.preventDefault();}
    }    </script>


  这个例子将拖放过过程涉及的事件做了一个罗列,这里不再细讲,你可以查看控制台看看事件的触发顺序和事件对象。

三、一个重要的对象DataTransfer对象

  这里首字母大写了,严格说叫做一个类,每一次拖放会实例化这个类,保存在事件对象的dataTransfer属性中。其属性和方法见下表(来自:http://www.cnblogs.com/ijjyo/p/4316232.html)

  感谢这位兄台的总结,拿了你这么多东西,谢谢啊。

       

  

       

  下面做一些简单的测试

  关于effectAllowed和dropEffect,这里将前者置为effectAllowed后者用下拉列表选择,以便于看到不同的鼠标样式。

  


html>
    <meta>
    <title>testEvents</title>
    <style>
        .source{
            width: 50px;
            height: 50px;
            border: 1px solid red;
        }
        .process{
            width: 100px;
            height: 100px;
            border: 1px solid black;
            margin-top: 10px;
        }
        .dest{
            width: 100px;
            height: 100px;
            border: 1px solid green;
            margin-top: 10px;
        }
    </style>
    <select>
        <option>copy</option>
        <option>move</option>
        <option>link</option>
        <option>none</option>
    </select>
    <p></p>
    <p></p>
    <p></p>
    <script>
    window.onload=function(){        var source = document.getElementById("source");        var process = document.getElementById("process");        var dest = document.getElementById("dest");        var dpe = document.getElementById("dpe");        var dpev;

        dpe.onchange = function(){
            dpev = this.value;
        }        var sourceEle;

        source.addEventListener("dragstart",function(e){
            console.log("source dragstart");
            console.log(e);
            sourceEle = e.target;            var dt = e.dataTransfer;
            dt.effectedAllowed = "all";
        },false);

        dest.addEventListener("dragend",function(e){
            console.log("dest dragend");
            console.log(e);
            e.preventDefault();
        },false);

        dest.addEventListener("drop",function(e){
            console.log("dest drop");
            console.log(e);
            dest.appendChild(sourceEle);
            e.preventDefault();
            e.stopPropagation();
        },false);

        document.ondragover = function(e){
            e.dataTransfer.dropEffect = dpev;
            e.preventDefault();
        }
        document.ondrop = function(e){e.preventDefault();}
    }    </script>


  我在ubuntu chrome测试法现,都是一个手,但是置为none时拖不进去了,可能不同系统会有一些差别。

  关于setData()和getData()方法

   这两个是有关数据交换的方法,前者传两个参数,第一参数是一个mime类型字符串,第二个是数据;后者传一个参数,为mime类型。可用mime类型为text/plain,text/html,text/xml,text/uri-list.

  测试用例,将菜单的菜拖到记录本上。

  


html>
    <meta>
    <title>点菜</title>
    <style>
        .menu{
            width: 200px;
            height: 300px;
            border: 1px solid red;
            margin-right: 10px;
            float: left;
        }
        .record{
            width: 200px;
            height: 300px;
            border: 1px solid black;
            margin-right: 10px;
            float: left;
        }
    </style>
    
            
  • 糖醋排骨
  •         
  • 青椒肉丝
  •         
  • 武昌鱼
  •         
  • 手撕包材
  •         
  • 千叶豆腐
  •          
    
                 
    <script> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.onload&nbsp;=&nbsp;function(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;menu&nbsp;=&nbsp;document.getElementById("menu");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;record&nbsp;=&nbsp;document.getElementById("record"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;menu.addEventListener("dragstart",function(e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;dt&nbsp;=&nbsp;e.dataTransfer;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;tar&nbsp;=&nbsp;e.target;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(tar.tagName=="LI"){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.setData("text/plain",tar.innerHTML); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.effectedAllowed&nbsp;=&nbsp;"all"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record.addEventListener("drop",function(e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;li&nbsp;&nbsp;=&nbsp;document.createElement("li"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;li.appendChild(document.createTextNode(e.dataTransfer.getData("text/plain"))); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record.appendChild(li); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.stopPropagation(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record.addEventListener("dropend",function(e){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.preventDefault(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.addEventListener("dragover",function(e){e.preventDefault()},false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.addEventListener("drop",function(e){e.preventDefault()},false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;</script>


  关于setDragImage(Element img,long x,long y)

   这个方法是设置拖放时的图标的,第一个参数表是图标元素,第二个表示相对与光标的水平偏移,第三个是垂直的。

  还是前面的例子,在dragstart事件添加下面的代码,拖动时你会发现一只很大的手(不要被吓到);


var img = document.createElement("img");
                img.src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493802056263&di=232de2c30491e19f32833669ad5a67ae&imgtype=0&src=http%3A%2F%2Fstatic.freepik.com%2Ffree-photo%2Fone-finger_318-10333.jpg";
                dt.setDragImage(img,10,10);


 

 四、关于拖放数据传递

  上面的例子已经谈到了拖放的数据传递方法,这里在总结一下。

  1、通过dataTransfer的setData()和getData()方法传递

  2、通过闭包的方法,请参考开篇的例子。

五、总结

  HTML5的拖放api非常简洁实用,为我们省去了很多麻烦,如果没有它,我们可能需要通过mousedownmousemove等等事件才能实现上述功能。本文较为详细的介绍了相关api,希望对你有所帮助。关于拖放api的应用大家可以参看下面链接的文章,他做了一个拖放排序,这是一个比较常见的应用场景。

  大~熊同学的粉丝数正在逼近三位数,感谢各位园友的支持,大~熊会继续努力的! 

  参考:

  • http://www.cnblogs.com/ijjyo/p/4316232.html 

  • http://www.cnblogs.com/linxin/p/6794542.html

 

 

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

2026.11.12

80

15

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

2026.11.12

60

15

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

2026.11.12

40

15

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

140

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

120

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

120

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

100

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

80

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

100

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.3万人学习