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、事件:

EventOn Event HandlerDescription
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

 

posted @ 2019-07-01 11:26  虚无缥缈的云  阅读(2277)  评论(0编辑  收藏  举报