HTML5拖放API附带示例

拖放(Drag 和 drop)是HTML5标准的组成部分

拖放

拖放是一种常见的特性,即抓取对象以后拖放到其他位置。在 HTML5 中,拖放是标准的一部分,任何元素都可以被拖放。

浏览器支持

Internet Explorer 9 + 、Firefox、Opera 12 + 、Chrome 以及 Safari 5 + 支持拖放。

拖放API

draggable属性

如果希望一个网页元素可以被拖动,只需要将他的draggable属性设置为true,这个元素就可以拖动了。

<div draggable="true">拖动我试试</div>

事件

拖动的过程会触发许多事件,主要有下面这些:

  • dragstart:网页元素开始拖动时触发。
  • drag:被拖动的元素在拖动过程中持续触发。
  • dragenter:被拖动的元素进入目标元素时触发,应在目标元素监听该事件。
  • dragleave:被拖动的元素离开目标元素时触发,应在目标元素监听该事件。
  • dragover:被拖动元素停留在目标元素之中时持续触发,应在目标元素监听该事件。
  • drop:被拖动元素或从文件系统选中的文件,拖放落下时触发。
  • dragend:网页元素拖动结束时触发。

以上函数均可以指定回调函数:

draggableElement.addEventListener('dragstart', function(e) {
    alert('拖放开始!')
    console.log(e);
});

拖动过程中,鼠标移动事件将不会被触发。

dataTransfer对象

拖动过程中,回调函数接受的事件参数,有一个dataTransfer属性。它指向一个对象,包含了与拖动相关的各种信息。
dataTransfer对象的属性:

  • dropEffect:拖放的操作类型,决定了浏览器如何显示鼠标形状,可能的值为copy、move、link和none。
  • effectAllowed:指定所允许的操作,可能的值为copy、move、link、copyLink、copyMove、linkMove、all、none和uninitialized(默认值,等同于all,即允许一切操作)。
  • files:包含一个FileList对象,表示拖放所涉及的文件,主要用于处理从文件系统拖入浏览器的文件。
  • types:储存在DataTransfer对象的数据的类型。

dataTransfer对象的方法:

  • setData(format, data):在dataTransfer对象上储存数据。第一个参数format用来指定储存的数据类型,比如text、url、text/html等。
  • getData(format):从dataTransfer对象取出数据。
  • clearData(format):清除dataTransfer对象所储存的数据。如果指定了format参数,则只清除该格式的数据,否则清除所有数据。
  • setDragImage(imgElement, x, y):指定拖动过程中显示的图像。默认情况下,许多浏览器显示一个被拖动元素的半透明版本。参数imgElement必须是一个图像元素,而不是指向图像的路径,参数x和y表示图像相对于鼠标的位置。
draggableElement.addEventListener('dragstart', function(event) {
    event.dataTransfer.setData('text', 'Hello World!');
});

上面代码在拖动开始时,在dataTransfer对象上储存一条文本信息,内容为“Hello World!”。当拖放结束时,可以用getData方法取出这条信息。

dataTransfer对象允许在其上存储数据,这使得在被拖动元素与目标元素之间传送信息成为可能。

实例

简单拖放

/* html */
<ul id="drag-elements">
  <li id="A" draggable="true"><img src="1.jpg" alt="" /></li>
  <li id="B" draggable="true"><img src="2.jpg" alt="" /></li>
  <li id="C" draggable="true"><img src="3.jpg" alt="" /></li>
  <li id="D" draggable="true"><img src="4.jpg" alt="" /></li>
  <li id="E" draggable="true"><img src="5.jpg" alt="" /></li>
  <li id="F" draggable="true"><img src="6.jpg" alt="" /></li>
  <li id="G" draggable="true"><img src="7.jpg" alt="" /></li>
  <li id="H" draggable="true"><img src="8.jpg" alt="" /></li>
</ul>

/* css */
ul {
  margin:0 auto;
  width:800px;
}
ul:after{
  content:"";
  display:block;
  clear:both;
}
li {
  width:200px;
  height:125px;
  float:left;
  background-color:#CCC;
  text-align:center;
  line-height:120px;
  font-size:50px;
  color:#F60;
}
.dragStart img {
  width:200px;
  height:125px;
}
/* js */
var dragElements = document.querySelectorAll('#drag-elements li');
var elementDragged = null;
for (var i = 0; i < dragElements.length; i++) {
  dragElements[i].addEventListener('dragstart', function (e) {
    e.dataTransfer.setData('text', this.id);
    elementDragged = this;
  });
  dragElements[i].addEventListener('dragover', function (e) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    elementDragged.setAttribute('class', 'dragStart');
    return false;
  });
  dragElements[i].addEventListener('dragenter', function(e) {
    e.preventDefault();
    e.stopPropagation();
    if (this.id != elementDragged.id) {
      var tempInnerHtml = this.innerHTML;
      this.innerHTML = elementDragged.innerHTML;
      elementDragged.innerHTML = tempInnerHtml;
      elementDragged.removeAttribute('class');
      elementDragged = this;
    }
  });
  dragElements[i].addEventListener('dragleave', function(e) {
    e.preventDefault();
    e.stopPropagation();
    if (this.id != elementDragged.id) {
      this.removeAttribute('class');
    }
  });
  dragElements[i].addEventListener('drop', function (e) {
    e.preventDefault();
    e.stopPropagation();  
    var targetId = e.dataTransfer.getData('text');
    elementDragged.removeAttribute('class');
    return false;
  });
  dragElements[i].addEventListener('dragend', function (e) {
    elementDragged = null;
  });
};

拖放网元素

/* html */
<ul id="drag-elements">
    <li draggable="true">A</li>
    <li draggable="true">B</li>
    <li draggable="true">C</li>
</ul>
<ul id="drop-target"></ul>

/* css */
ul{
    min-height:100px;
    background-color:#EEE;
    margin:20px;
    padding: 0;
}
ul li{
    background-color:#CCC;
    padding:10px;
    margin-bottom:10px;
    list-style: none;
}

/* js */
// 获取dom元素
var target = document.querySelector('#drop-target');
var dragElements = document.querySelectorAll('#drag-elements li');

// 定义变量跟踪被拖动的元素
var elementDragged = null;

// 对可以拖放的元素绑定 dragstart 和 dragend 事件
for (var i = 0; i < dragElements.length; i++) {
  dragElements[i].addEventListener('dragstart', function(e) {
    e.dataTransfer.setData('text', this.innerHTML);
    elementDragged = this;
  });
  dragElements[i].addEventListener('dragend', function(e) {
    elementDragged = null;
  });
}

// 向目标元素绑定 dragover 事件,来处理元素拖动进入目标元素之后的事情
target.addEventListener('dragover', function(e) {
  e.preventDefault();
  e.dataTransfer.dropEffect = 'move';
  return false;
});

// 最后定义目标元素的 drop事件,将被拖动元素从原来的位置删除
target.addEventListener('drop', function(e) {
  e.preventDefault();
  e.stopPropagation();
  this.innerHTML = 'Dropped ' + e.dataTransfer.getData('text');
  document.querySelector('#drag-elements').removeChild(elementDragged);
  return false;
});

拖放文件

/* html */
<div id="target" title="拖动文件到这里">
  <div id="content"></div>
</div>

/* css */
#target{
  margin:10px;
  min-height:100px;
  max-height:600px;
  background-color:#EEE;
  border-radius:5px;
  overflow:auto;
}
#content{
  padding:10px;
  font-size:18px;
  line-height:25px;
}

/* js */
// 首先获取拖动的目标元素和内容展示区域
var target = document.querySelector('#target');
var contentDiv = document.querySelector('#content');

// 然后定义目标元素的dragover事件,定义了当文件进入目标元素后要做的事情
target.addEventListener('dragover', function(e) {
  e.preventDefault();
  e.stopPropagation();
  e.dataTransfer.dropEffect = 'copy';
  return false;
});

// 最后定义目标元素的drop事件,展示文件内容
target.addEventListener('drop', function(e) {
  e.preventDefault(); 
  e.stopPropagation();
  var fileList = e.dataTransfer.files;
  if (fileList.length > 0) {
    var file = fileList[0];
    var reader = new FileReader();
    reader.onloadend = function(e) {
      if (e.target.readyState == FileReader.DONE) {
        var content = reader.result;
        contentDiv.innerHTML = "File: " + file.name + "\n\n" + content;
      }
    }
    reader.readAsBinaryString(file);
  }
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容