运用HTML5原生拖动事件(drag)实现拖动效果

  拖动效果相信很多朋友都自己写过,不管你用原生JS还是Jquery要实现起来也很简单,但是今天我想介绍的是运用HTML5标准中定义的原生拖动事件实现拖动效果。

  一、背景:

    其实说是HTML5标准定义,其实最早在IE4中就有拖放功能的API,只是在IE4中,网页中只有两种对象可以拖放:图像和某些文本。并且在IE4中唯一有效的放置目标是文本框。到了IE5.5,拖放功能得到了扩展,让网页中的任何元素都可以拖放。最终HTML5以IE的实力为基础制定了拖放规范。FF3.5+,Safari3+和Chrome根据规范实现了原生拖放。

  二、事件:

    原生拖放中涉及到的事件分为分下列两个阶段:

     (1)拖动某元素时,该阶段会依次触发下列事件(该阶段的事件目标--即target或srcElement都是这个被拖动元素):  

         1>dragstart——鼠标移入目标元素并且按下左键触发。

         2>drag——dragstart触发后移动鼠标连续触发该事件(类似mousemove事件)

         3>dragend——拖动停止时触发(无论此时拖动元素在有效位置还是无效位置)。

      (2)当元素被拖动到一个有效的放置目标上时,触发下列事件(该阶段的事件目标--即target或srcElement都是这个目标元素):

         1>dragenter——只要有元素被拖动到放置目标上,就触发dragenter事件(类似mouseover)

         2>dragover——触发dragenter后在有效目标范围内移动时连续触发该事件

         3>dragleave——被拖动元素从目标范围内被拖出到目标范围外时触发

         4>drop——被拖动元素被放到了目标范围内(即在有效目标范围内松口鼠标左键)

            注意:这里dragleave和drop二者只能触发其一!

  三、定义放置位置:

     虽然所有元素都支持放置目标事件,但是这些元素默认情况下是不允许放置的,如果拖动元素经过不允许放置的元素,那无论怎样都无法触发drop事件。所    以我们必须先定义出放置的目标元素。

     定义目标元素也很简单,只要阻止dragenter和dragover事件的默认行为就可以了,假设我们的目标元素为一个id为drag-area的div,我们要把它定义成我    们的目标元素,只需下面代码就可以了:

 drag_area.ondragover=function(evt){     //阻止dragover的默认事件
        var evt=evt || window.event;
        if(typeof evt.preventDefault=="function"){
            evt.preventDefault();
        }else{
            evt.returnValue=false;
        }
    }
    drag_area.ondragenter=function(evt){   //阻止dragenter的默认事件
        var evt=evt || window.event;
        if(typeof evt.preventDefault=="function"){
            evt.preventDefault();
        }else{
            evt.returnValue=false;
        }
    }

    (有小伙伴可能会问了,啊~阻止默认事件不是可以直接用return false么,干嘛这么麻烦。的确,return false可以阻止默认事件和事件传播,而且我测试过,用return false;的确也可以达到相同效果。这里主要是firefox的一个问题,我的firefox是最新版本,直接用return false没有问题,但是据 http://blog.csdn.net/goldlevi/article/details/5721348 说,稍早一些的firefox版本如果dragenter和dragover没有设置preventDefault的话不会在该元素上触发drag事件的,偷个懒,就不自己测试其他firefox了~关于FF还有一点问题,后面会提到);

四.实现

  前面解释了一下自定义放置目标,这里具体的实现就不多说了(其实原理和普通实现差不多~)直接上代码:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html,charset=utf-8">
    <title></title>
    <style type="text/css">
        #drag-area{
            width: 500px;height:500px;
            border: 1px solid red;
            position: relative;
        }
        #my-img{
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="drag-area">
        <img src="pity.gif"  id="my-img">
    </div>
</body>
<script type="text/javascript">
    var my_img=document.getElementById("my-img");
    var drag_area=document.getElementById("drag-area");
    my_img.ondragstart=function(evt){       //在被拖动的元素的dragstart事件中取得坐标便宜
        var evt=evt || window.event;        //即代码中evt.clientX-this.offsetLeft和evt.clientY-this.offsetTop,并保存在dataTransfer对象中
        evt.dataTransfer.setData("text",(evt.clientX-this.offsetLeft)+";"+(evt.clientY-this.offsetTop));
    }
    drag_area.ondragover=function(evt){     //阻止dragover的默认事件
        var evt=evt || window.event;
        if(typeof evt.preventDefault=="function"){
            evt.preventDefault();
        }else{
            evt.returnValue=false;
        }
    }
    drag_area.ondragenter=function(evt){   //阻止dragenter的默认事件
        var evt=evt || window.event;
        if(typeof evt.preventDefault=="function"){
            evt.preventDefault();
        }else{
            evt.returnValue=false;
        }
    }
    drag_area.ondrop=function(evt){
        var evt=evt || window.event;
        var drag_data=evt.dataTransfer.getData("Text").split(";");//从dataTransfer对象中取出数据,并将字符串分割成数组
        var offset_x=drag_data[0],//取得横向偏移
                offset_y=drag_data[1];//取得纵向偏移
        if(typeof evt.preventDefault=="function"){ //阻止drop事件的默认行为
            evt.preventDefault();
        }else{
            evt.returnValue=false;
        }
       my_img.style.left=(evt.clientX-offset_x)+"px";//给拖动元素的left,top赋值
        my_img.style.top=(evt.clientY-offset_y)+"px";
    }
</script>
</html>

   代码限定了被拖动元素(my_img)只能在(drag_area)这个500*500的div里面拖动。代码中我们在拖放元素的dragstart事件中取得了鼠标点击时的坐标偏移evt.clientX-this.offsetLeft和evt.clientY-this.offsetTop然后将其存放在dataTransfer对象中,

然后又在目标元素的drop事件里从dataTransfer对象中取出了偏移值,用来计算拖动元素的left和top。

   解释下dataTransfer这个对象。该对象是事件对象的一个属性,通常我们在利用它在被拖动元素(如代码中的my_img)dragstart事件处理程序中设置它的值,在目标元素(代码中的drag_area)drop事件(并且只能在drop事件)中读取其值,此外,浏览器在我们拖动文本(图片/链接)时,会自动将拖动的文本(url)存放在该对象中。

    设置dataTransfer内容的语法如下:

          event.dataTransfer.setData("数据类型","值")——这里数据类型虽然HTML定义了多种MIME类型,但是最好根据情况只使用

                                   ‘text’—保存字符串和’URL‘—保存url(ie只定义了这两种类型);

                                    值当然就是你需要的值啦。

    通过dataTransfer对象提取数据语法如下:

          event.dataTransfer.getData("数据类型")——这里数据类型同setData中的数据类型。

    另外dataTransfer对象还有两个属性,dropEffect和EffectAllowed。不过个人感觉很鸡肋,就不多说了,只是改了下鼠标的样式有木有啊~

  好了,有兴趣的同学把图片链接换一下试试吧~该方法兼容性尚可:opera不支持没话说,在IE6+,chrome中都没问题,但是在FF中拖动图片会自动打开图片的url,而且阻止不了(代码中drop事件有阻止默认代码~测试版本ff31.0和ff32.03)=_=!根本不科学嘛~希望看到本文,有解决方法的大神留言。

  总结一下,虽然我们用mousedown、mousemove、mouseup也能方便做出拖放效果,而且没有上面说的兼容性和FF中的BUG,但是如果项目不需要兼容opera,而且是拖拽选中文本的话,此方法就比较方便了(上面说过,拖拽文本浏览器会自动将选中并拖拽的文本、URL存放在dataTransfer对象中)。而且,做前端不就是折腾么。。。。

时间: 2024-08-24 11:13:37

运用HTML5原生拖动事件(drag)实现拖动效果的相关文章

HTML5实战与剖析之原生拖拽(四可拖动dragable属性和其他成员)

可拖动dragable属性 之前我们已经为大家介绍过几篇有关HTML5中原生拖拽的相关知识了.今天为大家介绍HTML5拖拽中的其他一些小东东,闲话不多说赶快一起看看吧. 在默认情况下,链接.文本和图像是可以拖动的,不用再写代码即可拖动.如果想让其他元素标签也可以拖动,那么只有HTML5能实现了.HTML5为所有HTML元素规定了dragable属性,表示元素是否可以拖动.链接和图像的标签中自动将dragable属性自动被设置成true,其他元素的dragable属性的默认值是false. 支持d

HTML5 元素拖动 - 实现元素左右拖动, 或更改自身排序

1.拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放是一种常见的特性,即抓取对象以后拖到另一个位置.在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 浏览器支持:Internet Explorer 9.Firefox.Opera 12.Chrome 以及 Safari 5 支持拖放(注:在 Safari 5.1.2 中不支持拖放.). 2.相关属性及方法  设置元素为可拖放,把 draggable 属性设置为 true <labeldraggable="tr

H5拖动事件复习

定义和用法 ondrag 事件在元素或者选取的文本被拖动时触发. 拖放是 HTML5 中非常常见的功能. 更多信息可以查看我们 HTML 教程中的 HTML5 拖放. 注意: 为了让元素可拖动,需要使用 HTML5 draggable 属性. 提示: 链接和图片默认是可拖动的,不需要 draggable 属性. 在拖放的过程中会触发以下事件: 在拖动目标上触发事件 (源元素): ondragstart - 用户开始拖动元素时触发 ondrag - 元素正在拖动时触发 ondragend - 用户

事件-拖动事件

本章节讲述的是拖动事件.具体看下面的代码 drag.html <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script src="drag.js" type="text/javascript"></script> &l

Android长按及拖动事件探究

Android中长按拖动还是比较常见的.比如Launcher中的图标拖动及屏幕切换,ListView中item顺序的改变,新闻类App中新闻类别的顺序改变等.下面就这个事件做一下分析. 就目前而言,Android中实现长按事件响应有几种方式,包括: 设置View.OnLongClickListener监听器 通过GestureDetector.OnGestureListener间接获取长按事件 实现View.OnTouchListener,然后在回调中通过MotionEvent判断是否触发了长按

原生拖拽,拖放事件(drag and drop)

原生拖拽,拖放事件(drag and drop) 拖拽,拖放事件可以通过拖拽实现数据传递,达到良好的交互效果,如:从操作系统拖拽文件实现文件选择,拖拽实现元素布局的修改. drag and drop事件流程 一个完整的drag and drop流程通常包含以下几个步骤: 设置可拖拽目标.设置属性draggable="true"实现元素的可拖拽. 监听dragstart设置拖拽数据 为拖拽操作设置反馈图标(可选) 设置允许的拖放效果,如copy,move,link 设置拖放目标,默认情况

IIViewDeckController拖动事件与百度地图拖动事件冲突

在使用第三方(IIViewDeckController)的侧边栏和百度地图同时使用时.发现百度地图的拖动事件被侧边栏截取了,导致拖动地图时地图移动缓慢,几乎无法滑动.在网上苦苦搜寻了解决方案,最终搜索到比较靠谱的http://www.cocoachina.com/bbs/read.php?tid-252890-page-2.html链接里面11楼的评论.但是我按照他的办法添加代码,在我这边还是没有效果.于是我就在IIViewDeckController第三类里面去找- (BOOL)gesture

HTML5原生拖放实例分析

原文链接:http://www.cnblogs.com/zhenwen/p/5855107.html HTML5提供了原生拖放功能的JavaScript API,使用起来很方便. 兼容性: 对于PC端浏览器,Firefox.Chrome.Safari支持良好,而IE和Edge浏览器有些特性不支持,如IE10和IE11.Edge对于dataTransfer.setData(format,data) ,只定义了"text"和"URL"两种有效的数据类型.而HTML5规范

教你使用HTML5原生对话框元素,轻松创建模态框组件

HTML 5.2草案加入了新的dialog元素.但是是一种实验技术. 以前,如果我们想要构建任何形式的模式对话框或对话框,我们需要有一个背景,一个关闭按钮,将事件绑定在对话框中的方式安排我们的标记,找到一种将消息传递出去的方式对话......这真的很复杂.对话框元素解决了上述所有问题. 一.Bootstrap模态框和原生模态框的对比 下面是一个bootstrap模态框的html结构: <!-- 按钮触发模态框 --> <button class="btn btn-primary