欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用HTML5的本机拖放API

程序员文章站 2022-05-26 20:44:14
...

每个人都喜欢一个易于使用和交互式用户界面和自推出智能手机的不断出现了来自用户的期望跳跃; 人们期望,你的网站将是直观的,将使用普遍理解的行为,并证明了整体一个简单的方法来浏览您的网站。

给你的用户的能力,拖放,和排序,使您的网站更直观的人了解如何元素X移动到位置Y和在对象B的前面移动的对象A使对象A是第一位的。

处理拖动,删除和排序一直是JavaScript和开发任务之前已经有建立自己的相互作用或以的选择使用预置的解决方案 随着HTML5拖放API的出现,开发人员将能够挂接到本地事件和属性来处理这些相互作用。

简介

让我们去通过API,所以我们可以得到它是如何工作的概述。

本机API可以让我们定义是通过使用可拖动的元素draggable="true"您想要的元素属性。 一些元件是由默认拖动即使没有任何修改(如图片或文本)。

使用HTML5的本机拖放API

默认情况下,当可拖动的元素被拖动,只有form元素如input将能够接受他们的下落。 你会看到在此之前, 如果你选择一些文本并将其拖动到一个textarea文本复制到textarea元素。

使用HTML5的本机拖放API

原生API还处理来自您的操作系统的外部区域拖放到你的拖放区。 几乎所有的优秀的内容管理系统提供的内容拖放上传。 因为这些元件外,所有你需要的配置是拖放区(也有兼容的浏览器)。

使用HTML5的本机拖放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); 

拖动相关活动

这些事件仅在拖动物品触发。

的dragstart
当我们开始拖动就会被触发。 它在这里,我们需要告诉API什么,我们将拖动并设置其他值。 使用setData()方法来设置要保存数据,设置effectAllowed属性为拖动元素,并定义了可拖动的辅助setDragImage()

拖动
此事件是拖在不断地触发。 它发生的次数取决于浏览器。 这是准确确定在何处可拖动的项目是非常有用的。

dragend
这一旦是事件触发的拖动被丢弃(不论在何地被丢弃的),一般下区的后直接触发drop事件。 您可以使用此事件重置拖动或执行其他清理动作时,应用的样式。 dragend事件访问可拖动,所以你可以拖动已经结束(例如,如果看到后做计算drop事件是寻找新加入的元素,然后删除原来的可拖动的成功)。

投递相关活动

这些事件仅在您指定为放置目标的元素(或已经自然随之下降的目标,如表单元素)触发:

的dragenter
只有一次,只要一个可拖动进入可投放区域时触发。 当拖动超过50%的下降区间内这将触发。

本次活动设置dropEffect拖放区。 默认情况下,滴在非表单元素不会做任何事情。 您将需要手动调用event.preventDefault()event.stopPropagation()来告诉这一下降应该发生的API。

您可以检查dataTransfer的对象effectAllowed已被拖动了设定值,然后把它比作你的落区有其价值dropEffect 如果这些值不会一起工作(即一个copy ,另一个是link ),那么浏览器将无法成功删除的项目(即使你避免违约,并停止传播)。

您可以使用types属性来获取已在设定的所有数据类型的列表dragstart事件。 你看不到的数据,但你可以看到它的类型。 它在这里你可以使用另一种方法称为contains ,看是否有某种类型的数据已经建立。 这是通过完成event.dataTransfer.types.contains(type)的方法。 您可以使用它来保证的东西已经被设置为text/html类型的例子。

现在你可以说你知道你拖动已进入降落区(一个共同的主题是风格拖放区不同来显示它被**的状态)设置类或触发动作。

的dragover
此事件在本质上是一样dragenter ,但它在不断呼吁,同时可拖动的项目是拖放区域内。 如果你想确定可拖动的确切位置(因为它在不断更新)此事件是完美的。

本次活动设置dropEffect拖放区,像dragenter ,则需要防止违约和传播。

dragleave
这是一次拖动已经从降级区搬走触发。 它一般用来删除相应的附加风格dragenterdragover事件和火灾一旦拖动不与下降区域相重合。

下降
一旦拖动已被释放触发此事件和拖放区域同意接受的下降。 这只会火如果拖动元素和拖放区域有正确的dropEffecteffectAllowed值。 在降,你将需要收集使用信息getData()方法。

拖放API方法

数据传递对象,我们将与本地拖放API打交道时与之交互的主要议题。 它暴露给我们作为事件的回调函数的一部分,并为我们提供了几个功能一起玩。

使用setData
此方法通过调用设置将来自可拖动要收集的数据event.datatransfer.setData(类型,数据)方法。 您需要在数据保存和数据本身的类型来传递。 这必须在设定dragstart事件或将失败。 它的价值只能在以后期间收集drop的事件。

type参数应该是一个适用的数据类型 您可以使用许多不同的类型,比如text/htmltext/uri-list ,如果你使用的是Chrome,Safari浏览器,或Firefox。 如果您正在使用Internet Explorer,您必须将其设置为TextURL (以这样认为的,否则会引起错误)。

data参数是要保存的数据。 您可以保存一个URL,HTML的一大块,或任何其它数据块。 您可以设置只有一个每一块数据的type 例如,如果你设置text/html是一些HTML,你不能再调用setData()再次以新的信息的方法,因为它会取代旧的内容。

的getData
这是对方的setData()方法和它的用于收集数据集由在拖动的元素startdrag事件。 您可以通过调用收集数据event.dataTransfer.getData(type) ,指定要收集的数据类型。

你很可能要检查哪些类型的使用设置event.dataTransfer.types看什么格式都已经过去了。 如果你尝试和访问数据尚未设置类型,Internet Explorer将抛出一个错误。

这种方法只能用于内部drop事件,因为只有在这一点上没有的API暴露值,这样你就可以收集它们(这是在传输过程中保护数据)。

clearData
这不正是它的名字所暗示的,它会清除使用任何数据集setData和它的格式书写的: event.dataTransfer.clearData(type) 您将需要指定被清除的数据类型(例如, text/htmlURL )。 这种方法只能在内部使用dragstart事件。

setDragImage
此方法设置使用格式拖动开始时要显示的拖动图像: event.dataTransfer.setDragImage() 。 默认情况下,拖动时,用户将看到他们拖着什么样的半透明图像。 使用这种方法,你可以定义自己的图像或元素在拖动的时候出现。 这部作品在除了IE的所有浏览器和目前还没有计划在它的包容工作要么

拖放API属性

有几个特性,我们可以在设置dataTransfer对象 我们使用则传递给我们从事件的回调来设置这些属性我们的活动变量。

effectAllowed
这是在拖动项中指定。 这讲述拖动事件和图标将被用于光标什么API(这是操作系统和浏览器的依赖)。 它通过将值分配给名为event.dataTransfer.effectAllowed里面dragstart事件,并采取可能的值copymovelinkcopyLinkcopyMovelinkMoveallnone ,或者uninitialized

如果此值不匹配dropEffect它会防止drop事件被称为(确保只有适当的下降发生)。

dropEffect来
这家酒店在降级区规定,并确定哪些拖动项目被允许在该区域下降。 应当通过指定的值event.dataTransfer.dropEffect过程中dragenterdragover事件。 dropEffect注意到的可能值copylinkmove ,或none

就像effectAllowed ,如果这个值不匹配effectAllowed它会防止drop事件被称为(确保只有适当的下降发生)。


此属性包含已设置的所有本地文件的列表。 它使用一种称为event.dataTransfer.files 只有所谓的文件已经从OS拖动到网页(如图像从桌面到您的网站的上传容器)。 此属性将永远是空的,如果一个普通的现场项目一直拖到(例如,如果你拖动图像,将有没有数据集files )。

它在这里,你可以检查看看,如果我们有文件。 如果我们这样做有他们,我们可以在读取和处理使用该文件的内容的FileReader对象

类型
此属性提供了已在当前的拖动设置的所有数据类型的列表。 通过使用称为event.dataTransfer.types方法。 这是在有用dragenterdragover事件,这样你可以看到什么数据类型已经确定。

effectAlloweddropEffect在行动

如果你是热衷于看你怎么能以务实的方式使用这些属性,看看下面的CodePen演示:

见笔本地拖放-在effectAllowed和DROPEFFECT性质由SitePoint( @SitePoint )上CodePen

在这里我们定义在那里他们可以掉落不同的物品拖动和设置。 我们还创建几个投掷的区域和一套可拖动的类型,他们将接受。 设置这些属性正确将确保您的浏览器知道其拖动项目允许被丢弃。

尽管Internet Explorer支持两种effectAlloweddropEffect的属性,它没有实现,只允许适用拖动到放置区的任何天生的能力。 Chrome浏览器,Safari浏览器和Firefox会限制你的拖拽项目,并防止不正确滴,拒绝火drop事件。 在IE浏览器,你将需要手动拒绝这些由值作为比较自己滴drop事件还是会火。

建立一些与本机API

有相当多的信息来处理的API让我们把一切融合在一起成为一个实际的例子。

本地API主要与拖动投掷的元素和它们的数据的传输之间的相互作用有关。 本机API不关心你走动尝试切换自己的立场两个元素,该API更关注的是它的数据和它的这个焦点,使得它独一无二的。

其中一件关于本机API的最好的事情是,它可以从多个位置处理不同类型的数据 ,也的数据

数据类型包括:

  • 纯文本字符串
  • 文/ HTML内容
  • URL列表
  • 单个或多个文件
  • 多种其他类型/自定义类型

数据位置包括:

  • 从内部元件被数据拖放
  • 从拖动元素的数据从一个不同的选项卡,窗口,或从不同的浏览器
  • 从本地源喜欢你的桌面数据

处理单元之间的数据拖放

本机API提供了基础知识,支持删除和元素的拖动。 虽然API提供了事件钩住知道,当一个成功的阻力已经发生,不像jQuery UI的,你需要手动移动/复制元素来调节API。

这是因为当你开始拖动的元素,你触发其dragStart在此期间,您将要传送的数据的事件(以及你希望你拖动有相应的效果,如复制,移动,链接等)。 当你终于放下你拖动的元素,IG是在正确的地方,会触发下降区域的drop事件。 它可以处理,你要移动的数据,而不是UI元素(你将需要手动使用JavaScript调整)。

让我们看一个实际的例子,所以你可以看到这是如何工作的。

例如:一拖和拖放益智游戏

看看下面的例子来看看如何使用API​​来在同一页面上的元素之间传输数据。

见笔机拖放-在单页上的数据传输由SitePoint( @SitePoint上) CodePen

我们正在做的这个例子是一个定义一系列的区域。 左侧将持有我们的主要拼图,而右侧有一系列的空落区。 在“游戏”是从左侧拖动件正确的,完成了这个难题。

在设置数据dragStart

dragStart事件对我们的拼图,我们首先将effectAllowed告诉项目,它接受一个copy基于拖累。

然后,我们收集src (图像源)和outerHTML (HTML节点),并把它们里面我们的数据传输对象为text/uri-listtext/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

之前,我们甚至下降的一块拼图,无论是dragEnterdragOver事件将触发。 请记住,我们能够下降,我们需要返回false /阻止默认告诉浏览器这是确定的下降。 这些功能都将设置下区的dropEffectcopy ,这意味着它会接受所有的拖拽项目copy作为他们effectAllowed (其中我们的项目正好有那么这一切都很好)。 我提到这一点,在这里,因为如果他们不匹配,则放置事件不会火,阻力将被取消。

我们滴收集数据

当我们我们的区域下降到正确的,我们使用getData方法提取我们的text/uri-listtext/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用户界面也可以做,什么jQuery UI的不能做的是让我们从任何外部标签,窗口或外部浏览器直接进入我们的拖放区域的能力拖动的内容。

有很多中,你已经看到了这个地方。 有几个网站中,你可以从一个选项卡中的图片直接进入下降区域和接收网站将采取互动的照顾。

为了获得最大的拖放,拖放区的必须配置,以便它知道如何处理它的接收(如基本如图像,文本,链接任何可拖动的元素中的数据和内容将被投进拖放区)。

拖动从桌面或本地设备上的内容的网页 ,并自动上传过程是那些革命性的功能,使你不知道我们怎么过有什么东西没有它做一个。

大多数CMS的(如WordPress的)具有通过拖拽和拖放接口原生支持的内容上传。 其他Web应用程序,如Gmail也提供这样的功能,让你可以直接拖放内容到区域,并自动连接,或将其存储使用。

例如:来自外部源的图像拖动

下一个例子将处理来自其他标签/窗口互动滴,让显示拖放区采集图像。

此外,例如也将处理局部下降的图像。 您将能够删除从您的桌面照片直接到悬浮窗和本机API将处理图像并显示出来。

使用HTML5的本机拖放API

如果你看到这一切是如何工作是敏锐的,这里的另一个CodePen演示:

见笔原生拖曳功能-直接拖动文件到网站由SitePoint( @SitePoint上) CodePen

什么这个例子的重点是处理掉落的物品。 不像我们,我们不得不对我们的拖放数据集其他例子,这一个,我们只需要收集数据,并确定我们将如何处理它。

里面我们主要drop功能,我们从我们收集的信息开始dataTransfer使用对象getData(format)方法。

 // 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';
} 

如果我们试图访问的格式里我们总结这一个try-catch块主要用于Internet Explorer,它会抛出一个错误,停止执行内部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和检查,看看是否这些出现在我们的网址之一。 如果确实如此,那么我们可以假设我们有一个形象。 我们创建了一个新的形象,用我们收集到的值作为其源。

处理本地掉落的物品

局部下降的元素有一点不同。 我们不使用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/htmltext/uri-list与自己的自定义类型一起)。 IE浏览器将只支持TextURL类型,你只限于你将如何处理你的数据,手段。
  • 在IE或边缘的任何版本的dataTransfer.setDragImage()方法不支持。 基本上没有设置自定义拖动图像或元件的能力。 你总是会得到浏览器的默认(其中大部分的时间将是半透明的元素的副本)。

对于移动,基本上为API没有实际的支持(2015年10月的)。 这可能与移动浏览器将如何处理自己作为通常你需要拖动和滚动走动的相互作用有关。 IE11是唯一的移动浏览器将支持它。

其他资源

有很多伟大的资源,以获取有关拖放API的更多细节。 他们中的一些讨论可用的方法和事件,你可以钩到,而其他细节浏览器不一致或轮廓很好的例子。

先从这些链接,这让我当我第一次寻找到本地拖放:

包起来

在这一点上,你现在应该有本机拖放API以及如何利用它来提供交互式界面的良好的基本认识。 你可能需要做的试验,以真正地开始了解很多,我在这里讨论什么的很多。

即使在缺乏移动支持,浏览器支持相当强劲,因此有充分的理由可以考虑使用原生API中的新项目。

From: https://www.sitepoint.com//html5-native-drag-and-drop-api/