基于JavaScript 实现拖放功能
作者:zhangbao90s 发布时间:2024-04-22 22:29:20
HTML 的拖放 API 依赖 DOM 事件模型,获取拖放和放置元素的相关信息,以此实现拖放功能。我们只需要注册很少几个事件 * ,就能把任何元素变成可拖动或可放置的。
拖放 API 除了提供基本的拖放功能接口外,还可以在拖放之外提供选择,用来自定义行为。比如,可以修改拖放元素的 CSS 样式。或者,我们不移动元素,拖动的时候,复制一个副本,拖放结束后,我们就会多了一个同样的元素。
本篇只介绍实现基本的拖放功能。
将元素设置成可拖动的
我们先从拖动元素开始。假设我们有一个容器元素,其中包含两种类型的子元素:可拖动元素和可放置元素。举个例子,如果我们有一个待办事项列表,我们可以将待办事项拖到“完成”区域。
简单起见,我们将移动的元素称为拖动元素,将拖动元素移入的目标元素称为 dropzone。
<div class='parent'>
<span id='draggableSpan'>
draggable
</span>
<span> dropzone </span>
</div>
这是我们的第一段代码,子元素现在还 不能 拖动。
下面给拖动元素添加属性 draggable='true'
,将它设置成一个可拖动元素。
<div class='parent'>
<span id='draggableSpan' draggable='true'>
draggable
</span>
<span> dropzone </span>
</div>
现在你再用鼠标拖动拖动元素的时候,它就会跟随鼠标移动(对不起,移动端不行:see_no_evil:)。
draggable
属性在没设置的情况下,默认值 auto
。就是说,元素是可不可以拖动,取决于浏览器的默认设置。比如,链接( <a>
)默认就是可拖动的,而 <span>
就不是。
拖放事件处理器
到目前为止,如果我们拖动元素,释放鼠标,什么事都不会发生。拖动和放置都会触发事件,实现一个基本的拖放功能,我们最少需要用到拖放 API 中的三个事件:
ondragstart
ondragover
ondrop
学会使用 ondragstart
、 ondragover
、 ondrop
事件只是个开始。拖拽过程一共会涉及八个事件: ondrag
、 ondragend
、 ondragenter
、 ondragexit
、 ondragleave
、 ondragover
、 ondragstart
和 ondrop
。
DataTransfer
DataTransfer
接口中保存了与当前拖放过程相关的跟踪信息,信息从 DataTransfer
对象属性中获得,而 DataTransfer
对象又是从 DOM 事件对象中获得的。
技术上讲, DataTransfer
接口可以同时跟踪多个拖动对象的信息,我们这里只关注拖动一个元素的情况。:sparkles:
拖动时更新元素
下一步,我们开始设置 ondragstart
的事件处理器。
拖动开始时,我们可以在 ondragstart
处理器中,做任何想做的修改。比如更新拖动元素的 CSS 样式,将拖动的版本设置为临时图片,或者其他能从 DOM 事件中访问到的任何内容。
dataTransfer
对象的 setData
属性可以用来设置拖动状态信息。它接收两个参数,第一个参数是表示内容格式的字符串,第二个参数是实际传递的数据。
我们要实现的功能是将拖动元素移动到一个新的父元素里面。我们需要获取拖动元素,因此需要将拖动元素的 ID 通过 setData
属性保存下来:
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
}
再从事件对象中获得拖动元素并设置 CSS 样式:
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
event
.currentTarget
.style
.backgroundColor = 'yellow';
}
注意:如果上面的黄色背景样式,你只希望在拖动时才应用,那么拖动结束后,就要手动将样式恢复。就会说,拖动开始时,如果修改了元素样式,除非再次修改过来,否则样式是不会自动恢复的。:rainbow:
拖动开始时的处理函数写好了,现在将它设置给可拖动元素的 ondragstart
属性:
<div class='parent'>
<span id='draggableSpan'
draggable='true'
ondragstart='onDragStart(event);'>
draggable
</span>
<span> dropzone </span>
</div>
下面是使用鼠标拖动时的效果:
现在拖动元素, ondragstart
中的代码就会执行,样式改变了,但释放拖动元素后,什么事情都没发生。接下来我们将视线转移到 dropzone 上来。
设置元素为可放置的
ondragstart
之后,下一个要写的处理函数就是 ondragover
了。上面讲过,放置行为默认是被浏览器阻止的,我们需要取消这个默认行为,双重否定为肯定,对吧?
function onDragOver(event) {
event.preventDefault();
}
在阻止浏览器干扰后,现在就能将拖动元素添加到 dropzone 了,dropzone 成为能够接受任何拖动元素的容器元素。
<div class='parent'>
<span id='draggableSpan'
draggable='true'
ondragstart='onDragStart(event);'>
draggable
</span>
<span ondragover='onDragOver(event);'>
dropzone
</span>
</div>
即便现在 dropzone 可以接受拖动元素,释放鼠标后还是看不见改变发生。
放置的时候要做什么?
现在要介绍第三个也是最后一个处理函数 ondrop
。
我们的函数逻辑遵循以下步骤:
还记得在
setData
中设置的数据吗?现在我们需要从
dataTransfer
对象的getData
属性中获取设置的数据,数据内容是拖动元素的 ID,它会返回给我们。使用上一步获取的 ID,获得拖动元素。 获取 dropzone 元素。
将拖拽元素 append 到 dropzone 中。
清理 dataTransfer 对象中保存的数据。
function onDrop(event) {
const id = event
.dataTransfer
.getData('text');
const draggableElement = document.getElementById(id);
const dropzone = event.target;
dropzone.appendChild(draggableElement);
event
.dataTransfer
.clearData();
}
因为这是我们要写的第三个也是最后一个函数,我们只要将它传递给 dropzone 的 ondrop
属性,就完成了一个完整的拖放功能!
<div class='parent'>
<span id='draggableSpan'
draggable='true'
ondragstart='onDragStart(event);'>
draggable
</span>
<span
ondragover='onDragOver(event);'
ondrop='onDrop(event);'>
dropzone
</span>
</div>
这里写的示例是最基本的,它展示如何使页面上的任何内容可变得可拖动。当然,一个网页里可以同时包含多个可拖动元素、多个 dropzone,或者使用文本没有介绍的其他事件做更加细粒度的自定义设置。
下面展示的是本文一开始提到的那个简单的待办事项列表功能。:fire:
只要依据本文上面已经讲过的内容,稍微变通一下,就能写出来。只要确保这里可拖动待办项目的 ID 是唯一的就行了。
总结
以上所述是小编给大家介绍的基于JavaScript 实现拖放功能,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://juejin.im/post/5d785e306fb9a06aca384834
猜你喜欢
- 实例如下所示:#!/usr/bin/python# -*- coding: UTF-8 -*-import reimport urllib,
- 目录前言🎪 一、Python 关键字🎢 二、Python标识符🎠 2.1 在 Python 中创建标识符的指南🎡 2.2 测试标识符是否有效
- python3下载抖音视频的代码如下所示:# -*- coding:utf-8 -*-from contextlib import clos
- 数据库性能优化普遍采用集群方式,oracle集群软硬件投入昂贵,今天花了一天时间搭建基于mysql的集群环境。主要思路简单说,实现mysql
- 本文实例讲述了mysql show操作。分享给大家供大家参考,具体如下:SHOW CHARACTER SET显示所有可用的字符集SHOW C
- Vue.js 的各种指令(Directives)更加方便我们去数据驱动 DOM,例如 v-bind、v-on、v-model、v-if、v-
- 某些时候我们需要让类动态的添加属性或方法,比如我们在做插件时就可以采用这种方法。用一个配置文件指定需要加载的模块,可以根据业务扩展任意加入需
- 学习要点:SQL之-建库、建表、建约束、关系SQL基本语句大全.txt举得起放得下叫举重,举得起放不下叫负重。头要有勇气,抬头要有底气。学习
- 前言随着Python3的普及,Selenium3也跟上了行程。而Selenium3最大的变化是去掉了Selenium RC,另外就是Webd
- 前言图像颜色的反转,比较简单的思路就是使用255减去当前值,从而得到反转后的图像.原始图片: 1.灰度图像的颜色反转import cv2im
- win7 64位下如何安装配置mysql-5.7.5-m15-winx64 距离上次安装MySQL已经过去好久了。步骤这些,有可能
- 切片是 Python 中最迷人最强大最 Amazing 的语言特性(几乎没有之一),在《Python进阶:切片的误区与高级用法》中,我介绍了
- 还有种片面的观点认为,做网站设计与平面差不多,比如老罗发布的这则招聘中提到:年薪十万招擅长做下列网站设计风格的平面设计师一名。在专业角度,网
- 1、块级作用域想想此时运行下面的程序会有输出吗?执行会成功吗?#块级作用域if 1 == 1: name = "lzl"
- 目标站点分析本次要抓取的目标站点为:中介网,这个网站提供了网站排行榜、互联网网站排行榜、中文网站排行榜等数据。网站展示的样本数据量是 :58
- explain显示了MySQL如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。简单讲,它的作用就
- 本文转自微信公众号:"算法与编程之美"1、前言侧滑是一个非常实用的选项组件,它在Android App应用中非常广泛,常
- Analyze Table MySQL 的Optimizer(优化元件)在优化SQL语句时,首先需要收集一些相关信息,其中就包括表的card
- 概要在列表,元组,实例,类,字典和函数中存在循环引用问题。有 __del__ 方法的实例会以健全的方式被处理。给新类型添加GC支持是很容易的
- 剑指Offer(Python多种思路实现):剪绳子面试14题:题目:剪绳子题:给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,且n