纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

js 拖拉时间之drag JavaScript 拖拉时间之drag案例详解

多纤果冻   2021-09-11 我要评论
想了解JavaScript 拖拉时间之drag案例详解的相关内容吗多纤果冻在本文为您仔细讲解js 拖拉时间之drag的相关知识和一些Code实例欢迎阅读和指正我们先划重点:js,drag,js,drag讲解下面大家一起来学习吧

拖拉(drag)指的是用户在某个对象上按下鼠标键不放拖动它到另一个位置然后释放鼠标键将该对象放在那里

拖拉的对象有好几种包括元素节点、图片、链接、选中的文字等等在网页中除了元素节点默认不可以拖拉其他(图片、链接、选中的文字)都是可以直接拖拉的为了让元素节点可拖拉可以将该节点的draggable属性设为true

<div draggable="true">
  此区域可拖拉
</div>

draggable属性可用于任何元素节点但是图片(<img>)和链接(<a>)不加这个属性就可以拖拉对于它们用到这个属性的时候往往是将其设为false防止拖拉这两种元素

注意一旦某个元素节点的draggable属性设为true就无法再用鼠标选中该节点内部的文字或子节点了

当元素节点或选中的文本被拖拉时就会持续触发拖拉事件包括以下一些事件

  • drag:拖拉过程中在被拖拉的节点上持续触发(相隔几百毫秒)
  • dragstart:用户开始拖拉时在被拖拉的节点上触发该事件的target属性是被拖拉的节点通常应该在这个事件的监听函数中指定拖拉的数据
  • dragend:拖拉结束时(释放鼠标键或按下 ESC 键)在被拖拉的节点上触发该事件的target属性是被拖拉的节点它与dragstart事件在同一个节点上触发不管拖拉是否跨窗口或者中途被取消dragend事件总是会触发的
  • dragenter:拖拉进入当前节点时在当前节点上触发一次该事件的target属性是当前节点通常应该在这个事件的监听函数中指定是否允许在当前节点放下(drop)拖拉的数据如果当前节点没有该事件的监听函数或者监听函数不执行任何操作就意味着不允许在当前节点放下数据在视觉上显示拖拉进入当前节点也是在这个事件的监听函数中设置
  • dragover:拖拉到当前节点上方时在当前节点上持续触发(相隔几百毫秒)该事件的target属性是当前节点该事件与dragenter事件的区别是dragenter事件在进入该节点时触发然后只要没有离开这个节点dragover事件会持续触发
  • dragleave:拖拉操作离开当前节点范围时在当前节点上触发该事件的target属性是当前节点如果要在视觉上显示拖拉离开操作当前节点就在这个事件的监听函数中设置
  • drop:被拖拉的节点或选中的文本释放到目标节点时在目标节点上触发注意如果当前节点不允许drop即使在该节点上方松开鼠标键也不会触发该事件如果用户按下 ESC 键取消这个操作也不会触发该事件该事件的监听函数负责取出拖拉数据并进行相关处理

下面的例子展示如何动态改变被拖动节点的背景色

div.addEventListener('dragstart', function (e) {
  this.style.backgroundColor = 'red';
}, false);
 
div.addEventListener('dragend', function (e) {
  this.style.backgroundColor = 'green';
}, false);

上面代码中div节点被拖动时背景色会变为红色拖动结束又变回绿色

下面是一个例子展示如何实现将一个节点从当前父节点拖拉到另一个父节点中

/* HTML 代码如下
 <div class="dropzone">
   <div id="draggable" draggable="true">
     该节点可拖拉
   </div>
 </div>
 <div class="dropzone"></div>
 <div class="dropzone"></div>
 <div class="dropzone"></div>
*/
 
// 被拖拉节点
var dragged;
 
document.addEventListener('dragstart', function (event) {
  // 保存被拖拉节点
  dragged = event.target;
  // 被拖拉节点的背景色变透明
  event.target.style.opacity = 0.5;
}, false);
 
document.addEventListener('dragend', function (event) {
  // 被拖拉节点的背景色恢复正常
  event.target.style.opacity = '';
}, false);
 
document.addEventListener('dragover', function (event) {
  // 防止拖拉效果被重置允许被拖拉的节点放入目标节点
  event.preventDefault();
}, false);
 
document.addEventListener('dragenter', function (event) {
  // 目标节点的背景色变紫色
  // 由于该事件会冒泡所以要过滤节点
  if (event.target.className === 'dropzone') {
    event.target.style.background = 'purple';
  }
}, false);
 
document.addEventListener('dragleave', function( event ) {
  // 目标节点的背景色恢复原样
  if (event.target.className === 'dropzone') {
    event.target.style.background = '';
  }
}, false);
 
document.addEventListener('drop', function( event ) {
  // 防止事件默认行为(比如某些元素节点上可以打开链接)
  event.preventDefault();
  if (event.target.className === 'dropzone') {
    // 恢复目标节点背景色
    event.target.style.background = '';
    // 将被拖拉节点插入目标节点
    dragged.parentNode.removeChild(dragged);
    event.target.appendChild( dragged );
  }
}, false);

关于拖拉事件有以下几个注意点

  • 拖拉过程只触发以上这些拖拉事件尽管鼠标在移动但是鼠标事件不会触发
  • 将文件从操作系统拖拉进浏览器不会触发dragstartdragend事件
  • dragenterdragover事件的监听函数用来取出拖拉的数据(即允许放下被拖拉的元素)由于网页的大部分区域不适合作为放下拖拉元素的目标节点所以这两个事件的默认设置为当前节点不允许接受被拖拉的元素如果想要在目标节点上放下的数据首先必须阻止这两个事件的默认行为
<div ondragover="return false">
<div ondragover="event.preventDefault()">

上面代码中如果不取消拖拉事件或者阻止默认行为就不能在div节点上放下被拖拉的节点

DragEvent 接口

拖拉事件都继承了DragEvent接口这个接口又继承了MouseEvent接口和Event接口

浏览器原生提供一个DragEvent()构造函数用来生成拖拉事件的实例对象

new DragEvent(type, options)

DragEvent()构造函数接受两个参数第一个参数是字符串表示事件的类型该参数必须;第二个参数是事件的配置对象用来设置事件的属性该参数可选配置对象除了接受MouseEvent接口和Event接口的配置属性还可以设置dataTransfer属性要么是null要么是一个DataTransfer接口的实例

DataTransfer的实例对象用来读写拖拉事件中传输的数据详见下文《DataTransfer 接口》的部分

DataTransfer 接口概述

所有拖拉事件的实例都有一个DragEvent.dataTransfer属性用来读写需要传递的数据这个属性的值是一个DataTransfer接口的实例

浏览器原生提供一个DataTransfer()构造函数用来生成DataTransfer实例对象

var dataTrans = new DataTransfer();

DataTransfer()构造函数不接受参数

拖拉的数据分成两方面:数据的种类(又称格式)和数据的值数据的种类是一个 MIME 字符串(比如text/plainimage/jpeg)数据的值是一个字符串一般来说如果拖拉一段文本则数据默认就是那段文本;如果拖拉一个链接则数据默认就是链接的 URL

拖拉事件开始时开发者可以提供数据类型和数据值拖拉过程中开发者通过dragenterdragover事件的监听函数检查数据类型以确定是否允许放下(drop)被拖拉的对象比如在只允许放下链接的区域检查拖拉的数据类型是否为text/uri-list

发生drop事件时监听函数取出拖拉的数据对其进行处理

DataTransfer 的实例属性

DataTransfer.dropEffect

DataTransfer.dropEffect属性用来设置放下(drop)被拖拉节点时的效果会影响到拖拉经过相关区域时鼠标的形状它可能取下面的值

  • copy:复制被拖拉的节点
  • move:移动被拖拉的节点
  • link:创建指向被拖拉的节点的链接
  • none:无法放下被拖拉的节点

除了上面这些值设置其他的值都是无效的

target.addEventListener('dragover', function (e) {
  e.preventDefault();
  e.stopPropagation();
  e.dataTransfer.dropEffect = 'copy';
});

上面代码中被拖拉元素一旦drop接受的区域会复制该节点

dropEffect属性一般在dragenterdragover事件的监听函数中设置对于dragstartdragdragleave这三个事件该属性不起作用因为该属性只对接受被拖拉的节点的区域有效对被拖拉的节点本身是无效的进入目标区域后拖拉行为会初始化成设定的效果

DataTransfer.effectAllowed

DataTransfer.effectAllowed属性设置本次拖拉中允许的效果它可能取下面的值

  • copy:复制被拖拉的节点
  • move:移动被拖拉的节点link:创建指向被拖拉节点的链接
  • copyLink:允许copylink
  • copyMove:允许copymove
  • linkMove:允许linkmove
  • all:允许所有效果
  • none:无法放下被拖拉的节点
  • uninitialized:默认值等同于all

如果某种效果是不允许的用户就无法在目标节点中达成这种效果

这个属性与dropEffect属性是同一件事的两个方面前者设置被拖拉的节点允许的效果后者设置接受拖拉的区域的效果它们往往配合使用

dragstart事件的监听函数可以用来设置这个属性其他事件的监听函数里面设置这个属性是无效的

source.addEventListener('dragstart', function (e) {
  e.dataTransfer.effectAllowed = 'move';
});
 
target.addEventListener('dragover', function (e) {
  ev.dataTransfer.dropEffect = 'move';
});

只要dropEffect属性和effectAllowed属性之中有一个为none就无法在目标节点上完成drop操作

DataTransfer.files

DataTransfer.files属性是一个 FileList 对象包含一组本地文件可以用来在拖拉操作中传送如果本次拖拉不涉及文件则该属性为空的 FileList 对象

下面就是一个接收拖拉文件的例子

// HTML 代码如下
// <div id="output" style="min-height: 200px;border: 1px solid black;">
//   文件拖拉到这里
// </div>
 
var div = document.getElementById('output');
 
div.addEventListener("dragenter", function( event ) {
  div.textContent = '';
  event.stopPropagation();
  event.preventDefault();
}, false);
 
div.addEventListener("dragover", function( event ) {
  event.stopPropagation();
  event.preventDefault();
}, false);
 
div.addEventListener("drop", function( event ) {
  event.stopPropagation();
  event.preventDefault();
  var files = event.dataTransfer.files;
  for (var i = 0; i < files.length; i++) {
    div.textContent += files[i].name + ' ' + files[i].size + '字节\n';
  }
}, false);

上面代码中通过dataTransfer.files属性读取被拖拉的文件的信息如果想要读取文件内容就要使用FileReader对象

div.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;
        div.innerHTML = 'File: ' + file.name + '\n\n' + content;
      }
    }
    reader.readAsBinaryString(file);
  }
});

DataTransfer.types

DataTransfer.types属性是一个只读的数组每个成员是一个字符串里面是拖拉的数据格式(通常是 MIME 值)比如如果拖拉的是文字对应的成员就是text/plain

下面是一个例子通过检查dataTransfer属性的类型决定是否允许在当前节点执行drop操作

function contains(list, value){
  for (var i = 0; i < list.length; ++i) {
    if(list[i] === value) return true;
  }
  return false;
}
 
function doDragOver(event) {
  var isLink = contains(event.dataTransfer.types, 'text/uri-list');
  if (isLink) event.preventDefault();
}

上面代码中只有当被拖拉的节点是一个链接时才允许在当前节点放下

DataTransfer.items

DataTransfer.items属性返回一个类似数组的只读对象(DataTransferItemList 实例)每个成员就是本次拖拉的一个对象(DataTransferItem 实例)如果本次拖拉不包含对象则返回一个空对象

DataTransferItemList 实例具有以下的属性和方法

  • length:返回成员的数量
  • add(data, type):增加一个指定内容和类型(比如text/htmltext/plain)的字符串作为成员
  • add(file)add方法的另一种用法增加一个文件作为成员
  • remove(index):移除指定位置的成员
  • clear():移除所有的成员

DataTransferItem 实例具有以下的属性和方法

  • kind:返回成员的种类(string还是file)
  • type:返回成员的类型(通常是 MIME 值)
  • getAsFile():如果被拖拉是文件返回该文件否则返回null
  • getAsString(callback):如果被拖拉的是字符串将该字符传入指定的回调函数处理该方法是异步的所以需要传入回调函数

下面是一个例子

div.addEventListener('drop', function (e) {
  e.preventDefault();
  if (e.dataTransfer.items != null) {
    for (var i = 0; i < e.dataTransfer.items.length; i++) {
      console.log(e.dataTransfer.items[i].kind + ': ' + e.dataTransfer.items[i].type);
    }
  }
});

DataTransfer 的实例方法

DataTransfer.setData()

DataTransfer.setData()方法用来设置拖拉事件所带有的数据该方法没有返回值

event.dataTransfer.setData('text/plain', 'Text to drag');

上面代码为当前的拖拉事件加入纯文本数据

该方法接受两个参数都是字符串第一个参数表示数据类型(比如text/plain)第二个参数是具体数据如果指定类型的数据在dataTransfer属性不存在那么这些数据将被加入否则原有的数据将被新数据替换

如果是拖拉文本框或者拖拉选中的文本会默认将对应的文本数据添加到dataTransfer属性不用手动指定

<div draggable="true">
  aaa
</div>

上面代码中拖拉这个<div>元素会自动带上文本数据aaa

使用setData方法可以替换到原有数据

<div
  draggable="true"
  ondragstart="event.dataTransfer.setData('text/plain', 'bbb')"
>
  aaa
</div>

上面代码中拖拉数据实际上是bbb而不是aaa

下面是添加其他类型的数据由于text/plain是最普遍支持的格式为了保证兼容性建议最后总是保存一份纯文本格式的数据

var dt = event.dataTransfer;
 
// 添加链接
dt.setData('text/uri-list', 'http://www.example.com');
dt.setData('text/plain', 'http://www.example.com');
 
// 添加 HTML 代码
dt.setData('text/html', 'Hello there, <strong>stranger</strong>');
dt.setData('text/plain', 'Hello there, <strong>stranger</strong>');
 
// 添加图像的 URL
dt.setData('text/uri-list', imageurl);
dt.setData('text/plain', imageurl);

可以一次提供多种格式的数据

var dt = event.dataTransfer;
dt.setData('application/x-bookmark', bookmarkString);
dt.setData('text/uri-list', 'http://www.example.com');
dt.setData('text/plain', 'http://www.example.com');

上面代码中通过在同一个事件上面存放三种类型的数据使得拖拉事件可以在不同的对象上面drop不同的值注意第一种格式是一个自定义格式浏览器默认无法读取这意味着只有某个部署了特定代码的节点才可能drop(读取到)这个数据

DataTransfer.getData()

DataTransfer.getData()方法接受一个字符串(表示数据类型)作为参数返回事件所带的指定类型的数据(通常是用setData方法添加的数据)如果指定类型的数据不存在则返回空字符串通常只有drop事件触发后才能取出数据

下面是一个drop事件的监听函数用来取出指定类型的数据

function onDrop(event) {
  var data = event.dataTransfer.getData('text/plain');
  event.target.textContent = data;
  event.preventDefault();
}

上面代码取出拖拉事件的文本数据将其替换成当前节点的文本内容注意这时还必须取消浏览器的默认行为因为假如用户拖拉的是一个链接浏览器默认会在当前窗口打开这个链接

getData方法返回的是一个字符串如果其中包含多项数据就必须手动解析

function doDrop(event) {
  var lines = event.dataTransfer.getData('text/uri-list').split('\n');
  for (let line of lines) {
    let link = document.createElement('a');
    link.href = line;
    link.textContent = line;
    event.target.appendChild(link);
  }
  event.preventDefault();
}

上面代码中getData方法返回的是一组链接就必须自行解析

类型值指定为URL可以取出第一个有效链接

var link = event.dataTransfer.getData('URL');

下面的例子是从多种类型的数据里面取出数据

function doDrop(event) {
  var types = event.dataTransfer.types;
  var supportedTypes = ['text/uri-list', 'text/plain'];
  types = supportedTypes.filter(function (value) { types.includes(value) });
  if (types.length) {
    var data = event.dataTransfer.getData(types[0]);
  }
  event.preventDefault();
}

DataTransfer.clearData()

DataTransfer.clearData()方法接受一个字符串(表示数据类型)作为参数删除事件所带的指定类型的数据如果没有指定类型则删除所有数据如果指定类型不存在则调用该方法不会产生任何效果

event.dataTransfer.clearData('text/uri-list');

上面代码清除事件所带的text/uri-list类型的数据

该方法不会移除拖拉的文件因此调用该方法后DataTransfer.types属性可能依然会返回Files类型(前提是存在文件拖拉)

注意该方法只能在dragstart事件的监听函数之中使用因为这是拖拉操作的数据唯一可写的时机

DataTransfer.setDragImage()

拖动过程中(dragstart事件触发后)浏览器会显示一张图片跟随鼠标一起移动表示被拖动的节点这张图片是自动创造的通常显示为被拖动节点的外观不需要自己动手设置

DataTransfer.setDragImage()方法可以自定义这张图片它接受三个参数第一个是<img>节点或者<canvas>节点如果省略或为null则使用被拖动的节点的外观;第二个和第三个参数为鼠标相对于该图片左上角的横坐标和右坐标

下面是一个例子

/* HTML 代码如下
 <div id="drag-with-image" class="dragdemo" draggable="true">
   drag me
 </div>
*/
 
var div = document.getElementById('drag-with-image');
div.addEventListener('dragstart', function (e) {
  var img = document.createElement('img');
  img.src = 'http://path/to/img';
  e.dataTransfer.setDragImage(img, 0, 0);
}, false);

相关文章

猜您喜欢

网友评论

Copyright 2020 www.sopisoft.net 【绿软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式