html5的元素拖拽

html5不仅新增了很多新标签(Element,比如canvas、math、video等等),也新增了很多新属性(Attribute),本章主要来介绍一下元素拖拽所使用的一系列属性(元素拖拽也是笔者在实际项目开发中经常使用的一个特性)。

下面就用一个例子来切入说明,不多废话,下面直接上代码干货:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>dragTest</title>
    <script>
        function allowDrop(e){
            e.preventDefault();
        }

        function drag(e){
            e.dataTransfer.setData("Text", e.target.id);
        }

        function drop(e){
            e.preventDefault();
            var data = e.dataTransfer.getData("Text");
            e.target.appendChild(document.getElementById(data));
        }
    </script>
</head>
<body>
    <p>拖拽测试</p>
    <div id="div1" style="width: 100px;height: 100px;border:1px solid #F00"
         ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <br>
    <img id="drag1" src="images/logo.png" draggable="true"
         ondragstart="drag(event)" width="80" height="80">
</body>
</html>


功能很简单,页面默认会显示一个红框以及一个自定义图片,这个自定义图片允许我们进行拖拽操作,而红框则允许拖入,我们可以手动把自定义图片拖入红框中。

下面来看一下默认显示的图片以及控制台的元素:

注意:如果有兴趣想自己在本地玩玩的同学记得创建一个images的目录,然后随便塞个图片进去。

然后尝试拖拽页面的图片(此时控制台部分未发生变化,截图未截取):

从上图可以看到,我们的自定义图片是允许拖拽的,但是红框外的区域是禁止拖入的,然后我们来看一下尝试拖拽到上面的红框中(此时控制台部分未发生变化,截图未截取):

从上图可以看到,红框内的区域是允许拖入的,最后我们来看一下拖入的结果以及控制台的元素:

图片完成了拖拽动作,从页面显示的元素信息可以看到,原本与div平级的img元素被拖入了div内部,整个拖拽功能完成。

功能介绍完了,我们再回顾一下代码,首先先看一下几个属性的含义:

ondragstart:包含ondragstart的元素被拖拽时触发此事件(调用ondragstart属性定义的函数)。

ondragover:当一个拖拽元素在包含ondragover的元素容器范围内拖动时触发此事件(调用ondragover属性定义的函数)。

ondrop:当一个拖拽元素在包含ondrop的元素容器内放置时触发此事件(调用ondrop属性定义的函数)。

draggable:声明包含draggable的元素是否允许被拖拽(true表示允许,false表示禁止)。

当然,如果想了解拖拽所涉及的所有属性,可以参考这个链接:html5拖放教程

然后来看一下例子里这几个属性对应的函数:

ondragstart:

        function drag(e){
            e.dataTransfer.setData("Text", e.target.id);
        }

dataTransfer对象用于保存拖拽元素的信息,setData就是保存信息函数,函数包含两个参数,第一个参数为保存信息的MIME类型,第二个参数为保存信息。例子里的drag函数就是当元素被拖拽时把元素的id记录在dataTransfer对象中(当元素在被拖入元素容器内放置时会使用该信息)。

ondragover:

        function allowDrop(e){
            e.preventDefault();
        }


preventDefault函数则是不要执行与事件关联的默认动作。因为元素是默认禁止其他元素在范围内拖动的,需要通过调用preventDefault函数来解禁。

ondrop:

        function drop(e){
            e.preventDefault();
            var data = e.dataTransfer.getData("Text");
            e.target.appendChild(document.getElementById(data));
        }


在ondrop函数内同样需要调用preventDefault函数,原因同上。第二句则是读取从之前的drag函数中的保存信息(即拖入元素的id),第三句则是把拖入元素拼为元素容器的最后一个子元素。

这样,一个完整的拖拽动作从代码的角度来解读可以分为三步(基于本例而言):

1.触发拖拽(鼠标左键点下),此时触发拖拽元素的ondragstart事件,在触发事件调用的函数中把拖拽元素的id记录在dataTransfer对象中;

2.开始拖拽(鼠标移动到元素容器范围内),此时触发元素容器的ondragover事件,在触发事件调用的函数中解禁元素容器禁止元素拖入;

3.停止拖拽(鼠标在元素容器范围内松开鼠标左键),此时触发元素容器的ondrop事件,在触发事件调用的函数中解禁元素容器禁止元素拖入,从dataTransfer对象中读取拖拽元素信息,并把拖拽元素拼为元素容器的最后一个子元素。

那么为什么在ondragover和ondrop事件中都需要做解禁元素禁止元素拖入的动作呢?我们试一试在ondrop事件调用的函数里去掉这个动作看看对整个拖拽过程有什么影响:

整个拖拽过程没有受到任何影响,也就是说ondragover事件做的解禁元素容器禁止元素拖入行为在ondrop事件触发时仍然是生效的。笔者认为,只要能够明确整个拖拽的流程(在本例中是先执行ondragover事件再执行ondrop事件),那么解禁元素容器禁止元素拖入的行为只需要在前一个事件中执行即可。

另外要注意的一点是,ondragover事件每隔几十毫秒就会触发一次,我们在事件调用的allowDrop函数里打上个时间戳看看情况:

从时间戳来看,ondragover事件调用的函数差不多每隔50~70毫秒左右就会执行一次,频率非常高,所以就不要在ondragover事件里处理复杂的业务逻辑了,尽量放在ondragenter事件里处理吧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值