整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

javascript 拖拽效果实现

拽原理

先介绍一下实现元素拖动需要的坐标属性,offsetLeft、offsetTop clientX、clientY。

offsetLeft 和offsetTop 用在dom节点中,可以返回当前元素距离某个父辈元素左边缘的距离。

clientX、clientY 在事件中使用,返回当事件被触发时鼠标指针向对于浏览器页面的水平坐标。

注:操作当前元素要定义成绝对定位

 //css
 #box{
 	width: 100px;
 	height: 100px;
 	background: red;
 	position: absolute;
 }


//dom元素
<div id="box"></div>

window.onload = function(){

 var drag = document.getElementById('box');//选择dom元素

 drag.onmousedown = function(event){
 var event = event || window.event; //兼容IE浏览器

 
 // 鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离

 var diffX = event.clientX - drag.offsetLeft; 
 var diffY = event.clientY - drag.offsetTop;

 if(typeof drag.setCapture !== 'undefined'){
 drag.setCapture(); 
 }

 document.onmousemove = function(event){

 var event = event || window.event;
 var moveX = event.clientX - diffX;
 var moveY = event.clientY - diffY;

 if(moveX < 0){//判断最左右边临界点
 moveX = 0
 }else if(moveX > window.innerWidth - drag.offsetWidth){
 moveX = window.innerWidth - drag.offsetWidth
 }

 if(moveY < 0){//判断最上下边临界点
 moveY = 0;
 }else if(moveY > window.innerHeight - drag.offsetHeight){
 moveY = window.innerHeight - drag.offsetHeight
 }

 drag.style.left = moveX + 'px';
 drag.style.top = moveY + 'px'
 console.log('x:'+moveX,'y:'+moveY);
 }

 document.onmouseup = function(event){ //鼠标松开 清除onmousemove、onmouseup事件

 this.onmousemove = null;
 this.onmouseup = null;
 //修复低版本ie bug 
 if(typeof drag.releaseCapture!='undefined'){ 
 drag.releaseCapture(); 
 } 
 }

 }
 }

拖拽效果

本文中,我们将了解HTML拖放,并借助示例了解其实现.

拖放是一个非常交互式和用户友好的概念,它可以通过抓住对象更轻松地将对象移动到其他位置。这允许用户在元素上单击并按住鼠标按钮,将其拖动到其他位置,然后释放鼠标按钮以将元素放到该位置。在HTML 5中,拖放更容易编码,其中的任何元素都是可拖动的。

拖放事件:有各种拖放事件,其中一些在下面列出:

  • ondrag: 它用于在 HTML 中拖动元素或文本选择时使用。
  • ondragstart: 它用于调用一个函数 drag(event),该函数指定要拖动的数据。
  • ondragenter: 它用于确定丢弃目标是否接受丢弃。如果要接受丢弃,则必须取消此事件。
  • ondragleave:当鼠标在拖动发生时将元素留在有效放置目标之前时,就会发生这种情况。
  • ondragover: 它指定可以放置拖动数据的位置。
  • ondrop:它指定在拖动操作结束时发生丢弃的位置。
  • ondragend: 当用户完成拖动元素时,就会发生这种情况。

拖放 Drag and Drop实现步骤:

  • 步骤1:使对象可拖动 首先将可拖动属性设置为 true,以使该元素可拖动 <img draggable = “true”>然后,指定拖动元素时应发生的情况。ondragstart 属性调用一个函数 drag(event),该函数指定要拖动的数据。dataTransfer.setData() 方法设置数据类型和拖动数据的值事件侦听器 ondragstart 将设置允许的效果(复制、移动、链接或某种组合).
  • 步骤2: 放下对象 ondragover 事件指定可以放下拖动数据的位置。默认情况下,不能将数据/元素放在其他元素中。若要允许删除,它必须阻止元素的默认处理。这是通过调用 event.preventDefault() 方法最后,drop 事件来完成的,它允许执行实际的丢弃

例1:

<!DOCTYPE HTML>
<html>
<head>
    <style>
    #getData {
        width: 250px;
        height: 200px;
        padding: 10px;
        border: 1px solid #4f4d4d;
    }
    </style>
    <script>
    function allowDrop(even) {
        even.preventDefault();
    }
 
    function drag(even) {
        even.dataTransfer.setData("text", even.target.id);
    }
 
    function drop(even) {
        even.preventDefault();
        var fetchData = even.dataTransfer.getData("text");
        even.target.appendChild(document.getElementById(fetchData));
    }
    </script>
</head>
 
<body>
    <h3>Drag the GeekforGeeks image into the rectangle:</h3>
    <div id="getData"
         ondrop="drop(event)"
         ondragover="allowDrop(event)">
      </div>
    <br>
    <img id="dragData"
         src="gfg.png"
         draggable="true"
         ondragstart="drag(event)"
         width="250"
         height="200">
</body>
</html>


Output:

Dragging the image into the box

拖放过程的数据传递: 当拖放的整个过程发生时,将使用数据传输属性。它用于保存从源拖放到所需位置的数据。这些是与之关联的属性:

  • dataTransfer.setData(format, data): 它用于设置要拖动的数据.
  • dataTransfer.clearData(format): 它用于调用此函数,没有清除所有数据的参数。使用 format 参数调用它仅删除该特定数据。
  • dataTransfer.getData(format): 它返回指定格式的数据。如果没有此类数据,则返回空字符串.
  • dataTransfer.types:此属性返回在 dragstart 事件中设置的所有格式的数组。
  • dataTransfer.files: 它用于返回要删除的所有文件。
  • dataTransfer.setDragImage(element, x, y): 它用于将现有图像显示为拖动图像,而不是光标旁边的默认图像。坐标指定放置位置。
  • dataTransfer.addElement(element): 它用于添加要绘制的指定元素作为拖动反馈图像。
  • dataTransfer.effectAllowed(value): 它将告诉浏览器只允许用户使用列出的操作类型。该属性可以设置为以下值:none、copy、copyLink、copyMove、link、linkMove、move、all 和未初始化。
  • dataTransfer.dropEffect(value): 它用于控制在拖动和拖动事件期间向用户提供的反馈。当用户将鼠标悬停在目标元素上时,浏览器的光标将指示将要发生的操作类型(例如复制、移动等)。效果可以采用以下值之一:无、复制、链接、移动。

例2:

<!DOCTYPE HTML>
<html>
<head>
<title>Drag and Drop box</title>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function dragStart(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function dragDrop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
<style>
#box {
margin: auto;
width: 50%;
height: 200px;
border: 3px solid green;
padding: 10px;
}
#box1,
#box2,
#box3 {
float: left;
margin: 5px;
padding: 10px;
}
#box1 {
width: 50px;
height: 50px;
background-color: #F5B5C5;
}
#box2 {
width: 100px;
height: 100px;
background-color: #B5D5F5;
}
#box3 {
width: 150px;
height: 150px;
background-color: #BEA7CC;
}
p {
font-size: 20px;
font-weight: bold;
text-align: center;
}
.gfg {
font-size: 40px;
color: #009900;
font-weight: bold;
text-align: center;
}
</style>
</head>
<body>
<div class="gfg">GeeksforGeeks</div>
<p>Drag and drop of boxes</p>
<div id="box">
<div id="box1" draggable="true"
ondragstart="dragStart(event)">
</div>
<div id="box2" draggable="true"
ondragstart="dragStart(event)">
</div>
<div id="box3" ondrop="dragDrop(event)"
ondragover="allowDrop(event)">
</div>
</div>
</body>
</html>


说明:

  • 通过将要拖动的元素的可拖动属性draggable设置为 true 来开始拖动。
  • 使用 dataTransfer.getData() 方法获取拖动的数据。此方法将返回在 setData() 方法中设置为相同类型的任何数据。
  • 调用 event.preventDefault() 方法,通过阻止元素的默认处理来允许删除其他元素中的元素。
  • 该元素存储在我们附加到放置元素中的变量数据中。

效果:

我们都知道普通的HTML自带的功能相对有限,很多复杂的交互式场景,如果手动去写功能的话会非常的复杂,而且可扩展性差,就拿HTML表格来说,对于初学者或者对于复杂的拖拽式交互编程不熟悉的话会很浪费时间,因此今天就介绍一个第三方的插件——Table-draagger,来轻松实现类似的功能。Table-draagger是用于构建可重排序的拖放表的极简主义纯Javascript库!



Github

https://github.com/sindu12jun/table-dragger


特征

Table-draagger因为其以下几个特征而让拖拽和排序的实现变得如此简单:

  • 非常容易配置
  • 能够同时对列或行进行排序
  • 排序时动画流畅
  • 没有臃肿的依赖
  • 提供触摸事件(意味着在触摸设备可以实现一些你想要的功能)


安装使用

  • 安装

可以在npm上获得它:

npm install table-dragger --save

或者引用压缩的js文件

<script src="../node_modules/table-dragger/dist/table-dragger.min.js"></script>

或者尝试开发中的不稳定版本

npm install table-dragger@next --save

  • 快速入门

请看以下代码:

import tableDragger from 'table-dragger'
tableDragger(el, options?)

<table id="table">
<thead>
<tr>
<th class='handle'>header1</th>
<th class='handle'>header2</th>
</tr>
</thead>
<tbody>
<tr>
<td>conten1</td>
<td>conten2</td>
</tr>
</tbody>
</table>

var el = document.getElementById('table');
var dragger = tableDragger(el, {
mode: 'row',
dragHandler: '.handle',
onlyBody: true,
});
dragger.on('drop',function(from, to){
console(from);
console(to);
});

你可以在不设置任何参数的情况下使用默认的拖拽和排序方式,当然以下是你可以配置的选项:

  • options.mode

1、将mode设置为column,用户拖动和排序表的列

2、将mode设置为row,用户拖动并排序表的行

3、设置mode为free,用户根据点击后鼠标移动的方向拖动行或列。注意,必须在自由模式下指定dragHandler。

  • options.dragHandler

dragHandler是表中的拖动句柄选择器默认情况下,在列模式下,dragHandler是表的第一行;在行模式下,则是第一列。

  • options.onlyBody

在行模式下将onlyBody设置为true时,用户只能在tbody中提升行。

  • API

下面是返回对象的API


tableDragger(document.querySelector('#event-table'), { mode: 'free', dragHandler: '.handle', onlyBody: true })
.on('drag', () => {
console.log('drag');
})
.on('drop', (from, to, el, mode) => {
console.log(`drop ${el.nodeName} from ${from} ${mode} to ${to} ${mode}`);
})
.on('shadowMove', (from, to, el, mode) => {
console.log(`move ${el.nodeName} from ${from} ${mode} to ${to} ${mode}`);
})
.on('out', (el, mode) => {
console.log(`move out or drop ${el.nodeName} in mode ${mode}`);
});


总结

Table-draagger为我们节省了很多手动封装表格排序和拖拽功能的时间,当然目前很多第三方框架已经实现了类似的功能,这更适用于原生的html表格,你还可以通过一些手段记忆用户拖拽,这只是其中一种思路,Enjoy it!~