html元素拖拽


二、基于HTML5拖拽API的拖拽
前序知识介绍
  一个典型的拖拽操作是这样的:用户用鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标。 在操作期间,会触发一些事件类型,有一些事件类型可能会被多次触发(比如drag 和 dragover 事件类型)。

一个完整的drag and drop流程通常包含以下几个步骤:

  1. 设置可拖拽目标.设置属性draggable="true"实现元素的可拖拽.
  2. 监听dragstart设置拖拽数据
  3. 为拖拽操作设置反馈图标(可选)
  4. 设置允许的拖放效果,如copy,move,link
  5. 设置拖放目标,默认情况下浏览器阻止所有的拖放操作,所以需要监听dragenter或者dragover取消浏览器默认行为使元素可拖放.
  6. 监听drop事件执行所需操作

  

这里涉及几个知识点:

1、可拖动元素:又称为源对象,是指我们鼠标点击之后准备拖动的对象(图片、div、文字等)
2、可放置元素:又称为目标对象,是指可以放置源对象的区域

3、事件:

Event On Event Handler Description
drag ondrag 当拖动元素或选中的文本时触发
dragend ondragend 当拖拽操作结束时触发 (比如松开鼠标按键或敲“Esc”键)
dragenter ondragenter 当拖动元素或选中的文本到一个可释放目标时触发
dragexit ondragexit 当元素变得不再是拖动操作的选中目标时触发
dragleave ondragleave 当拖动元素或选中的文本离开一个可释放目标时触发
dragover ondragover 当元素或选中的文本被拖到一个可释放目标上时触发
dragstart ondragstart 当用户开始拖动一个元素或选中的文本时触发
drop ondrop 当元素或选中的文本在可释放目标上被释放时触发

                 ps:当从操作系统向浏览器中拖动文件时,不会触发dragstart 和dragend 事件

4、接口:

HTML5为所有的拖动相关事件提供了一个新的属性:

event.DataTransfer对象

属性和方法

描述

dropEffect 拖拽交互类型,通常决定浏览器如何显示鼠标光标并控制拖放操作.常见的取值有copy,move,linknone
effectAllowed 指定允许的交互类型,可以取值:copy,move,link,copyLink,copyMove,limkMoveallnone默认为uninitialized(允许所有操作)
files 包含File对象的FileList对象.从操作系统向浏览器拖放文件时有用.
types 保存DataTransfer对象中设置的所有数据类型.
setData(format, data) 以键值对设置数据,format通常为数据格式,如text,text/html
getData(format) 获取设置的对应格式数据,format与setData()中一致
clearData(format) 清除指定格式的数据
setDragImage(imgElement, x, y) 设置自定义图标

 

源对象和目标对象的事件间传递数据

event.dataTransfer {}//数据传递对象

源对象上的事件处理中保存数据:

event.dataTransfer.setData(key,value);//key,value必须都是字符串类型
如:
event.dataTransfer.setData("text/plain", "This is text to drag");

更多的数据类型参考

目标对象上的事件处理中读取数据:

var value2 = event.dataTransfer.getData(key);

兼容性

demo

<div id="demo1">
  <ul class="panel-list">
    <li class="panel-item"></li>
    <li class="panel-item"></li>
    <li class="panel-item"></li>
    <li class="panel-item"></li>
    <li class="panel-item"></li>
  </ul>
  <h2>拖拽下面的方块到上面任意容器中</h2>

  <!-- 设置draggable使元素成为可拖拽元素 -->
  <div class="movable" id="demo1-src" draggable="true" draggable="true">
      <img style="width:100%;" src="__ADMIN__/img/pbl/11.jpg">
  </div>

  <style>
    #demo1 {
      margin: 20px;
    }
    #demo1 .panel-list {
      overflow: hidden;
      list-style: none;
      margin: 0;
      padding: 0;
    }
    #demo1 .panel-item {
      float: left;
      margin-right: 30px;
      width: 100px;
      height: 100px;
      background: #ddd;
      border: 1px solid #ddd;
    }
    #demo1-src {
      display: inline-block;
      width: 50px;
      height: 50px;
      background: purple;
    }
    #demo1 .over {
      border: 1px dashed #000;
      -webkit-transform: scale(0.8, 0.8);
    }
  </style>
  <script>
  (function () {

    var dnd = {
      // 初始化
      init: function () {
        var me = this;
        me.src = document.querySelector('#demo1-src');//获取指定css选择器的元素
        me.panelList = document.querySelector('.panel-list');//获取指定css选择器的元素
        console.log( me.panelList );
        //addEventListener('要监听的事件名','事件触发的函数',布尔:指定事件是否在捕获或冒泡阶段执行)
        // 为拖拽源监听dragstart,设置关联数据
        me.src.addEventListener('dragstart', me.onDragStart, false);

        // 拖拽鼠标移入元素,在拖放目标上设置视觉反馈
        me.panelList.addEventListener('dragenter', me.onDragEnter, false);

        // 取消元素dragover默认行为,使其可拖放
        me.panelList.addEventListener('dragover', me.onDragOver, false);

        // 拖拽移出元素,清除视觉反馈
        me.panelList.addEventListener('dragleave', me.onDragLeave, false);

        // 鼠标释放,在拖放目标上接收数据并处理
        me.panelList.addEventListener('drop', me.onDrop, false);
      },
      onDragStart: function (e) {
        //setData(format, data) 以键值对设置数据,format通常为数据格式,如text,text/html   
        //设置可拖动元素的id(存起来)
        e.dataTransfer.setData('text/plain', 'demo1-src');
       e.target.style.height="100px";
       e.target.style.cursor="move";
      },
      //当拖动元素或选中的文本到一个可释放目标时触发
      onDragEnter: function (e) {
        console.log(e.target);
        //e.target : <ul class="panel-list"></ul>
        //panel-list元素的子元素的类名列表中包含panel-item类则添加over类(呈现虚框效果)
        if (e.target.classList.contains('panel-item')) {
          //为panel-item的元素添加over类
          e.target.classList.add('over');
        }
      },
      //当拖动元素或选中的文本离开一个可释放目标时触发(移除over类)
      onDragLeave: function (e) {
        e.target.style.cursor="move";
        if (e.target.classList.contains('panel-item')) {
          e.target.classList.remove('over');
        }
      },
      //当元素或选中的文本被拖到一个可释放目标上时触发(取消事件的默认动作比如说表单自动提交)
      onDragOver: function (e) {
        e.preventDefault();
      },
      //当元素或选中的文本在可释放目标上被释放时触发
      onDrop: function (e) {
        var id = e.dataTransfer.getData('text/plain');
        var src = document.getElementById(id);
        var target = e.target;
        if (target.classList.contains('panel-item')) {
          target.appendChild(src);
          target.classList.remove('over');
        }
      }

    };

    dnd.init();
  }());
  </script>
</div>


<div id="demo2">
  <h3>从文件夹中拖拽图片到下面的区域进行预览</h3>
  <ul class="preview"></ul>
  <style>
  #demo2 {
    margin: 20px;
  }
  #demo2 .preview {
    height: 300px;
    background: #ddd;
  }
  #demo2 li {
    float: left;
    margin-left: 40px;
  }
  #demo2 img {
    max-height: 150px;
    width: auto;
  }
  </style>

  <script>
  (function (w) {
    var doc = w.document;

    var dnd = {
      init: function () {
        var me = this;
        var preview = doc.querySelector('#demo2 .preview');

        preview.addEventListener('dragover', function (e) {
          e.preventDefault();
        }, false);

        preview.addEventListener('drop', function (e) {
          // 操作系统拖放文件到浏览器需要取消默认行为
          e.preventDefault();

          [].forEach.call(e.dataTransfer.files, function (file) {
            if (file && file.type.match('image.*')) {
              var reader = new FileReader();

              reader.onload = function (e) {
                var img = doc.createElement('img');
                img.src = e.target.result;
                var li = doc.createElement('li');
                li.appendChild(img);
                preview.appendChild(li);
              };

              reader.readAsDataURL(file);
            }
          });
        }, false);
      }

    };

    dnd.init();
  }(window));
  </script>
</div> <!-- demo2 -->
View Code

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM