html5拖放api
每个人都喜欢易于使用和交互式的用户界面,并且自从引入智能手机以来,用户的期望就不断提高。 期望您的网站将是直观的,将使用普遍理解的操作,并且总体上证明了与网站互动的简便方法。
由于人们了解如何将元素X移动到位置Y,并且对象B前面的移动对象A使对象A成为第一位用户,因此赋予用户用户拖放和排序的能力可使您的站点更加直观。
拖放,排序和排序一直是JavaScript的任务,并且开发人员以前可以选择构建自己的交互或使用预构建的解决方案 。 随着HTML5拖放API的出现 ,开发人员将能够加入本机事件和属性来处理这些交互。
简介
让我们浏览一下API,以便我们可以大致了解其工作原理。
原生API允许我们通过在所需元素上使用draggable="true"
属性来定义可拖动的元素。 默认情况下,某些元素即使不进行任何修改也可以拖动(例如图像或文本)。
默认情况下,拖动可拖动元素时,只有input
form
元素才能将其接受为放置。 您可能以前已经看过; 如果选择一些文本并将其拖动到textarea
该文本将被复制到textarea
元素中。
本机API还可以处理从操作系统外部区域到拖放区的拖动。 几乎所有好的内容管理系统都可以拖放内容。 由于这些元素是外部的,因此您只需配置拖放区(并且还具有兼容的浏览器)即可。
关于移动设备的快速说明
当前,本机API不支持移动设备。 尽管将来可能会有所改变,但最好从桌面浏览器中查看示例,以便您了解其工作原理
拖放API事件
本机API提供了以下事件 ,您可以监听。 这些事件将应用于可拖动项目或放置区域 ,并将在设置的时间触发。
触发这些事件后,我们可以访问本地对象(我们将其称为event
)。 该对象包含有关事件本身的更多信息,并将使您可以访问dataTransfer
对象,在其中将设置大多数方法和属性。
我们需要将回调函数挂接到每个事件上,以便我们可以与API进行交互:
// add a handler to trigger on dragstart
document.addEventListener('dragstart', function(event) {
// add your dragstart code here
}, false);
拖曳相关事件
这些事件仅在可拖动项目上触发。
拖动开始
一开始拖动就触发。 在这里,我们需要告诉API我们将要拖动的内容并设置其他值。 使用setData()
方法设置要保存的数据,设置可拖动元素的effectAllowed
属性,并使用setDragImage()
定义可拖动帮助器。
拖动
在拖动过程中会连续触发此事件。 发生次数取决于浏览器。 这对于确定可拖动项目的确切位置很有用。
拖曳
这是事件,一旦拖放到可拖动对象(无论它放置在什么地方),就会触发该事件,并且通常在放置区域的drop
事件之后立即触发。 您可以使用此事件来重置拖动时应用的样式,或执行其他清除操作。 dragend
事件可以访问可拖动对象,因此您可以在拖动结束后进行计算(例如,通过查找新添加的元素然后删除原始可拖动对象来查看drop
事件是否成功)。
掉落相关事件
这些事件仅在您指定为放置目标的元素上触发(或者已经自然成为放置目标,例如表单元素):
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
德拉贡特
只要可拖动对象进入可放置区域,就会触发一次。 当超过50%的可拖动对象位于放置区域内时,这将触发。
此事件设置放置区域的dropEffect
。 默认情况下,放置在非格式元素上不会执行任何操作。 您将需要手动调用event.preventDefault()
和event.stopPropagation()
来告诉API应该发生此删除操作。
您可以在dataTransfer
对象中检查可拖动对象设置的effectAllowed
值,然后将其与放置区域的dropEffect
值进行比较。 如果这些值不能一起使用(即一个是copy
,另一个是link
),则浏览器将不会成功删除该项目(即使您阻止了默认设置并停止了传播)。
您可以使用types
属性获取在dragstart
事件中设置的所有数据类型的列表。 您看不到数据,但可以看到其类型。 在这里,您可以使用另一个名为contains
方法来查看是否已设置某种类型的数据。 这是通过event.dataTransfer.types.contains(type)
方法完成的。 例如,您可以使用它来确保已将某些内容设置为text/html
类型。
现在,您就知道您的可拖动对象已进入拖放区(您可以将拖放区的样式设置为不同以显示其已被激活),就可以设置类或触发操作。
拖曳
此事件本质上与dragenter
相同,但是在可拖动项位于放置区域内时会连续调用此事件。 如果您想确定可拖动对象的确切位置(因为它会不断更新),则此事件是完美的。
此事件设置拖放区的dropEffect
,就像dragenter
一样,您将需要防止默认设置和传播。
拖曳
一旦可拖动对象从放置区域移开,就会触发此操作。 通常用于删除在dragenter
或dragover
事件中添加的样式,并在可拖动对象与放置区域不重叠时触发。
下降
一旦释放了可拖动对象并且放置区域同意接受放置,就会触发此事件。 仅当可拖动元素和放置区域具有正确的dropEffect
和effectAllowed
值时effectAllowed
。 拖放时,您将需要使用getData()
方法收集信息。
拖放API方法
dataTransfer对象是在处理本机拖放API时将与之交互的主要项目。 它作为事件的回调函数的一部分提供给我们,并为我们提供了几个可以使用的函数。
setData
此方法通过调用event.datatransfer.setData(type,data)方法设置将从可拖动对象收集的数据 。 您将需要输入要保存的数据类型和数据本身。 这必须在dragstart
事件中设置,否则将失败。 其值只能在drop
事件期间稍后收集。
type
参数应为适用的数据类型 。 如果您使用的是Chrome,Safari或Firefox,则可以使用许多不同的类型,例如text/html
或text/uri-list
。 如果您使用的是Internet Explorer,则必须将其设置为“ Text
或“ URL
(否则将导致错误)。
data
参数是您要保存的数据。 您可以保存一个URL,一段HTML或任何其他数据。 每个type
只能设置一个数据。 例如,如果将text/html
设置为HTML,则不setData()
使用新信息再次调用setData()
方法,因为它将替换旧内容。
getData
这是setData()
方法的对应方法,它用于在startdrag
事件期间收集由拖动的元素设置的数据。 您可以通过调用event.dataTransfer.getData(type)
来收集数据,指定要收集的数据类型。
您很可能必须使用event.dataTransfer.types
检查设置了哪些类型,以查看已传递了哪些格式。 如果您尝试访问尚未设置的数据类型,则Internet Explorer将引发错误。
此方法只能在drop
事件内部使用,因为仅在那时API会公开这些值,以便您可以收集它们(这是为了在传输期间保护数据)。
clearData
这确实符合其名称的含义,它使用setData
清除任何数据集,并以以下格式编写: event.dataTransfer.clearData(type)
。 您将需要指定要清除的数据类型(例如text/html
或URL
)。 此方法只能在dragstart
事件内使用。
setDragImage
此方法设置拖动开始时使用以下格式显示的拖动图像: event.dataTransfer.setDragImage() 。 默认情况下,拖动时,用户将看到他们正在拖动的东西的半透明图像。 使用此方法,您可以定义自己的图像或元素,以在拖动过程中显示。 该功能适用于Internet Explorer以外的所有浏览器,并且目前也没有计划的工作 。
拖放API属性
我们可以为dataTransfer
对象设置几个属性 。 我们使用从事件回调传递给我们的事件变量来设置这些属性。
效果允许
这是在可拖动项上指定的。 这告诉API有关拖动事件以及将用于光标的图标(这取决于操作系统和浏览器)。 通过在dragstart
事件内为event.dataTransfer.effectAllowed分配一个值来调用它,并采用copy
, move
, link
, copyLink
, copyMove
, linkMove
, all
, none
或未uninitialized
的可能值。
如果此值与dropEffect
不匹配,它将阻止调用drop
事件(确保仅发生适当的drop)。
dropEffect
此属性在放置区域上指定,并确定允许哪些拖动项放置在该区域上。 在dragenter
或dragover
事件期间,应通过event.dataTransfer.dropEffect
为其分配一个值。 dropEffect
接受copy
, link
, move
或none
的可能值。
就像effectAllowed
一样,如果此值与effectAllowed
不匹配,它将防止调用drop
事件(确保仅发生适当的drop操作)。
档案
此属性包含已设置的所有本地文件的列表。 使用event.dataTransfer.files
调用。 只有被调用的文件才从OS拖到网站上(例如,从桌面到网站上载容器的图像)。 如果已拖动常规的现场项目,则此属性将始终为空(例如,如果拖动图像,则不会为files
设置数据)。
您可以在这里查看我们是否有文件。 如果我们有它们,我们可以使用fileReader对象读入并处理文件的内容。
类型
此属性提供当前拖动中已设置的所有数据类型的列表。 使用event.dataTransfer.types
方法调用。 这在dragenter
和dragover
事件期间很有用,以便您可以查看已设置的数据类型。
effectAllowed
和dropEffect
作用
如果您热衷于了解如何以实际方式使用这些属性,请查看以下CodePen演示:
见笔本地拖放-在effectAllowed和DROPEFFECT性质由SitePoint( @SitePoint )上CodePen 。
在这里,我们定义了不同的可拖动项目,并设置了它们可以放置的位置。 我们还创建了几个可放置区域,并设置了它们将接受的可拖动类型。 正确设置这些属性将确保您的浏览器知道允许拖放哪些可拖动项目。
即使Internet Explorer同时支持effectAllowed
和dropEffect
属性,它也未实现任何本机功能,仅允许将适用的拖动拖入拖放区。 Chrome,Safari和Firefox将限制您的拖动项目并防止不正确的放置,并拒绝触发drop
事件。 在IE上,您将需要通过比较值来手动拒绝这些丢弃,因为drop
事件仍然会触发。
使用本机API构建内容
有关API的信息很多,因此让我们将所有内容放到一个实际的示例中。
本地API主要与拖动和投掷的元素和它们的数据的传输之间的相互作用有关。 本机API并不关心您是否在移动两个元素来尝试切换它们的位置,API更关心其数据,正是这种关注使其独特。
关于本机API的最好的事情之一是它可以处理不同类型的数据 ,也可以处理来自多个位置的数据 。
数据类型包括:
- 纯文本字符串
- 文字/ HTML内容
- 网址清单
- 单个或多个文件
- 多种其他类型/自定义类型
数据位置包括:
- 来自内部元素的数据被拖放
- 来自其他选项卡,窗口或其他浏览器中可拖动元素的数据
- 来自本地资源(如台式机)的数据
拖放处理元素之间的数据
本机API提供了支持元素拖放的基础。 尽管与jQuery UI不同,API提供了一些事件以供您了解成功拖动的发生时间,但与jQuery UI不同,您将需要手动移动/复制元素来调整API。
这是因为在开始拖动元素时,会触发它的dragStart
事件,在该事件期间设置要传输的数据(以及您希望可拖动对象具有的适当效果,例如复制,移动,链接等)。 当您最终放下拖动的元素时,如果它在正确的位置,它将触发放置区域的drop
事件。 它处理您要移动的数据,而不处理UI元素(您需要使用JavaScript手动进行调整)。
让我们看一个实际的例子,以便您了解它是如何工作的。
示例:拖放益智游戏
看下面的示例,看看如何使用API在同一页面上的元素之间传输数据。
见笔机拖放-在单页上的数据传输由SitePoint( @SitePoint上) CodePen 。
在此示例中,我们正在定义一系列区域。 左侧将容纳我们的主要拼图碎片,而右侧则具有一系列空落区。 “游戏”是将棋子从左向右拖动,完成拼图。
在dragStart
上设置数据
在我们的拼图块的dragStart
事件中,我们首先设置effectAllowed
以告知项目它接受基于copy
的拖动。
然后,我们收集src
(图像源)和outerHTML
(HTML节点),并将它们作为text/uri-list
和text/html
放入我们的数据传输对象中。 如果我们在Internet Explorer上,则只保存要拖动的元素的src
并将其保存为text
格式。
var dragItem;
// triggered draggable as we start dragging
function dragStart(event) {
drag = event.target;
dragItem = event.target;
// set the effectAllowed for the drag item
event.dataTransfer.effectAllowed = 'copy';
var imageSrc = $(dragItem).prop('src');
var imageHTML = $(dragItem).prop('outerHTML');
// check for IE (it supports only 'text' or 'URL')
try {
event.dataTransfer.setData('text/uri-list', imageSrc);
event.dataTransfer.setData('text/html', imageHTML);
} catch (e) {
event.dataTransfer.setData('text', imageSrc);
}
$(drag).addClass('drag-active');
}
正确effectAllowed
/ dropEffect
在我们放下拼图之前, dragEnter
和dragOver
事件都会触发。 请记住,要使我们能够删除,我们需要返回false / prevent default来告诉浏览器可以删除。 这些功能都将设置下区的dropEffect
来copy
,这意味着它会接受所有的拖拽项目copy
作为他们effectAllowed
(其中我们的项目正好有那么这一切都很好)。 我在这里提到这个是因为如果它们不匹配,则不会触发drop事件,并且拖动将被取消。
收集数据
当我们将区域拖放到右侧时,我们使用getData
方法提取我们的text/uri-list
和text/html
数据集。 如果没有它们(如果正在Internet Explorer上访问),则只需提取text
数据。
这是我们根据拥有的数据而有所不同的地方。 如果可以访问dataHTML
则意味着我们使用的是受完全支持的浏览器,并且可以访问整个拖动的节点。 如果这样做,我们将整个项目添加到放置区域中,放置完成。
如果我们没有支持我们需要克隆dragItem
我们设置回到dragStart
事件获得节点。 然后,我们将其添加到放置区域并完成所有操作。
// called when draggable is dropped on droppable
function drop(event) {
drop = this;
$(drop).removeClass('drop-active');
var dataList, dataHTML, dataText;
// collect our data (based on what browser support we have)
try {
dataList = event.dataTransfer.getData('text/uri-list');
dataHTML = event.dataTransfer.getData('text/html');
} catch (e) {
dataText = event.dataTransfer.getData('text');
}
// we have access to the HTML
if (dataHTML) {
$(drop).empty();
$(drop).prepend(dataHTML);
// check if this element is in the right spot
checkCorrectDrop(drop, dragItem);
// see if the final image is complete
checkCorrectFinalImage();
}
// only have access to text (old browsers + IE)
else {
$(drop).empty();
$(drop).prepend($(dragItem).clone());
// check if this element is in the right spot
checkCorrectDrop(drop, dragItem);
// see if the final image is complete
checkCorrectFinalImage();
}
event.preventDefault();
event.stopPropagation();
}
完成游戏
两个放置事件都调用checkCorrectDrop(drop, dragItem)
和checkCorrectFinalImage()
函数。 这些用于我们的游戏。
checkCorrectDrop()
函数检查拖动项和放置区的名为data-value
的自定义属性是否相同。 如果这两个都相同,则此作品属于此处,并以绿色边框(和active
班级)突出显示。
checkCorrectFinalImage()
函数检查所有拼图块是否都已放入正确的位置。 如果我们有正确的项目与要拖动的项目一样多,则意味着我们已经完成了难题–万岁!
从其他选项卡和桌面本地移动数据
使用本机API,您可以定义将接受拖动元素的放置区域。 虽然这听起来像jQuery UI也可以完成,但是jQuery UI不能做的是使我们能够将内容从任何外部选项卡,窗口或外部浏览器直接拖动到放置区域中。
您已经在很多地方看到了这一点。 在几个网站中,您可以将图像从一个选项卡直接拖动到放置区域,接收网站将负责交互。
为了充分利用拖放功能,必须对放置区域进行配置,使其知道如何处理其接收的数据(因为基本上任何可拖动的元素(例如图像,文本,链接和内容)都将放入拖放区)。
将内容从台式机或本地设备拖到网页上并自动执行上传过程是这些革命性的功能之一,这使您想知道如果没有它,我们将如何完成工作。
大多数CMS(例如WordPress)都具有通过拖放界面上传内容的本机支持。 Gmail等其他网络应用程序也提供了此功能,可让您将内容直接放入区域并自动附加或存储以供使用。
示例:从外部源拖动图像
下一个示例将处理来自其他选项卡/窗口的交互式放置,让放置区域收集图像进行显示。
此外,该示例还将处理本地丢弃的图像。 您将能够将照片从桌面直接拖放到放置区,并且本机API将处理图像并显示它们。
如果您热衷于了解这一切的工作原理,请参见下面的另一个CodePen演示:
见笔原生拖曳功能-直接拖动文件到网站由SitePoint( @SitePoint上) CodePen 。
本示例着重于处理掉落的物品。 与我们不得不在拖动上设置数据的其他示例不同,对于此示例,我们仅需要收集数据并确定我们将如何处理它。
在主要的drop
函数内部,我们首先使用getData(format)
方法从dataTransfer
对象收集信息。
// get the URL of elements being dragged here
try {
dataValue = event.dataTransfer.getData('text/uri-list');
dataType = 'text/uri-list';
} catch (e) {
dataValue = event.dataTransfer.getData('URL');
dataType = 'URL';
}
我们将此内容包装在主要用于Internet Explorer的try-catch块中,如果尝试在getData()
中访问它无法理解的格式,则会抛出错误并停止执行。
如果我们能够以text/uri-list
格式获取数据,则将其收集; 如果不能,我们将退回到使用基本URL
属性。
大多数拖动的项目(例如图像,链接或数据)会遇到几种数据类型。 由于我们只对这些项目的URL感兴趣,因此效果很好。
如果我们设置了dataValue
,则意味着用户将某些东西放到了我们的区域中。 现在,我们需要弄清楚它是什么。 我们只想处理图像,但是由于API无法区分图像URL和标准链接,因此我们需要做一些检查以确保我们删除图像。
// determine if our URL is an image
imageDropped = false;
var imageExtensions = ['.jpg','.jpeg','.png','.bmp','.gif'];
for (i = 0; i< imageExtensions.length; i++) {
if (dataValue.indexOf(imageExtensions[i]) !== -1) {
// create our image to add
var image = '<img src="' + dataValue + '">';
drop.append(image);
imageDropped = true;
break;
}
}
我们创建具有已知图像类型(例如.jpg
和.png
的图像扩展名列表,并检查其中是否有一个出现在我们的URL中。 如果是这样,那么我们可以假设我们有一个图像。 我们创建一个新图像并将收集的值用作其来源。
处理本地掉落的物品
局部删除的元素有些不同。 我们不使用getData(format)
方法来获取这些,而是使用files()
方法。 这将为我们提供已删除的所有元素的列表,以便我们可以遍历它们。
var dataFiles = event.dataTransfer.files;
var dataOutput = [];
if (dataFiles) {
for (i =0; i < dataFiles.length; i++) {
// do processing here
}
}
对于我们的示例,我们要浏览所有删除的文件,并检查是否有图像。 当我们遍历每个文件时,我们可以访问一系列属性,包括type
属性,该属性列出了项目的mime类型。
// check if this is an image
if (dataType.match('image.*')) {
// it's an image, process further
}
如果匹配图像类型,则创建一个新的fileReader对象,该对象将用于将文件读入内存。 我们使用readAsDataURL(item)
方法读取文件,当文件准备就绪时,它将触发其onload
事件,我们将对其进行进一步处理。
// read into memory
var reader = new FileReader();
// load element
reader.readAsDataURL(dataItem);
我们现在要做的就是收集文件阅读器的结果,并将其添加到DOM中。 我们已成功将图像从桌面拖动到我们的网站!
// when our image is loaded
reader.onload = (function(theFile) {
return function(e) {
var url = e.target.result;
drop.append('<img src="' + url + '" title="' + dataName + '"/>');
messageContainer.append('
<p><strong>Successfully dropped an image from your desktop</strong></p>
');
};
})(dataItem);
浏览器支持概述
顾名思义,该API为开发人员提供了一组事件和方法,他们可以使用这些事件和方法来提供UI交互,而无需第三方JavaScript库。
总体而言,浏览器具有强大的桌面支持,几乎没有移动支持,因此它将在遵循该规范的大多数现代桌面浏览器中正常运行。 Internet Explorer虽然有其自己的一系列独特问题。
桌面支持非常好,Chrome,Firefox,Safari和Opera都具有全面的支持。 另一方面,Internet Explorer对API的处理方式不同,根据您所使用的版本,支持不同的方面。 例如:
- IE7,IE8和IE9中不支持
dataTransfer.files
或.types
对象。 这意味着在IE9之前,您将无法使用本机拖放功能来允许用户将文件从桌面拖放到网页上。 -
dataTransfer.setData/getData
受支持有限格式在实践中,当我们拖动项目时,我们需要将数据存储在拖放中可以在拖放中访问的数据。 在其他浏览器中,您可以将其存储为多种类型(例如text/html
或text/uri-list
)以及自己的自定义类型。 IE仅支持Text
或URL
类型,这意味着您只能处理数据。 - IE或Edge的任何版本均不支持dataTransfer.setDragImage()方法。 基本上,无法设置自定义拖动图像或元素。 您将始终获得浏览器的默认值(大多数情况下,它是半透明元素的副本)。
对于移动设备,该API基本上没有实际支持(截至2015年10月)。 这可能与移动浏览器如何自行处理交互有关,因为通常您需要拖动和滚动才能移动。 IE11是唯一支持它的移动浏览器。
其他资源
有很多很棒的资源可以获取有关拖放API的更多详细信息。 其中一些讨论了可用的方法和您可以挂接的事件,而其他一些则详细介绍了浏览器不一致或概述了出色的示例。
从这些链接开始,当我第一次研究本机拖放时,这些链接对我有所帮助:
- 在HTML5 Rocks上进行本机HTML5拖放
- Dottoro Web参考上的dataTransfer对象
- Mozilla 拖放介绍
结语
至此,您现在应该对本地的拖放API以及如何利用它提供交互式界面有了很好的基本了解。 您可能需要做很多实验才能真正开始理解我在这里讨论的很多内容。
即使缺乏移动支持,浏览器的支持也非常强大,因此有充分的理由考虑在新项目中使用本机API。
翻译自: https://www.sitepoint.com/html5-native-drag-and-drop-api/
html5拖放api