HTML5、JS实现元素拖拽排序

news2024/11/16 2:22:35

在这里插入图片描述
先介绍一下html5的drag属性,拖放(Drag 和 drop)是 HTML5 标准的组成部分。想要启用drag,只要给元素加上draggable="true"就行了(Safari 5.1.2除外)。

拖动事件
事件分为两类,当前拖动的元素上的事件,以及要放置的位置接收到的事件。
一.发生在拖动元素上的事件:

事件名 触发时机 触发次数
dragstart 当拖动开始时触发一次 1
drag 拖动开始后反复触发 n
dragend 拖动结束后触发一次

二.发生在目标元素上的事件

事件名 触发时机 触发次数
dragenter 当拖动元素进入目标时触发一次 1
dragover 当拖动元素在目标元素范围内时反复触发 n
drop 拖动元素在目标元素内释放时(在设置了dropover事件的前提下) 1

信息传递

在拖动元素时可以设置传递的信息
event.dataTransfer.setData(“te”, “sss);
两个参数,第一个参数key,第二个参数value。
注意只能传递字符串和url,但是在firefox使用text或Text作为key时会打开新的标签页,所以不要用他们作为key。

注意:设置了dragover后drop才会触发!!

下面是代码实例:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
           list-style: none;
           margin: 0;
           padding: 0;
       }

       #container{
           width: 500px;
           margin: 100px auto;
       }

        .ele {
            width:100%;
            height: 40px;
            border: 1px solid #999;
            background: cadetblue;
            margin-top: 2px;
            border-radius: 10px;
            padding-left: 10px;
            color: white;
            cursor: move;
        }
    </style>
</head>
<body>
<ul id="container">
    <li class="ele" draggable="true">1</li>
    <li class="ele" draggable="true">2</li>
    <li class="ele" draggable="true">3</li>
    <li class="ele" draggable="true">4</li>
</ul>
<script>
    var node = document.querySelector("#container");
    var draging = null;
    //使用事件委托,将li的事件委托给ul
    node.ondragstart = function(event) {
        //console.log("start");
        //firefox设置了setData后元素才能拖动!!!!
        //event.target出发事件的元素
        event.dataTransfer.setData("te", event.target.innerText); //不能使用text,firefox会打开新tab
        //event.dataTransfer.setData("self", event.target);
        draging = event.target;
    }
    node.ondragover = function(event) {
        //console.log("onDrop over");
        //取消默认行为
        event.preventDefault();
        var target = event.target;
        //因为dragover会发生在ul上,所以要判断是不是li
        if (target.nodeName === "LI") {
            if (target !== draging) {
                //getBoundingClientRect()用于获取某个元素相对于视窗的位置集合
                var targetRect = target.getBoundingClientRect();
                var dragingRect = draging.getBoundingClientRect();
                if (target) {
                    if (target.animated) {
                        return;
                    }
                }
                if (_index(draging) < _index(target)) {
                    //nextSibling 属性可返回某个元素之后紧跟的节点(处于同一树层级中)。
                    target.parentNode.insertBefore(draging, target.nextSibling);
                } else {
                    target.parentNode.insertBefore(draging, target);
                }
                _animate(dragingRect, draging);
                _animate(targetRect, target);
            }
        }
    }
    //获取元素在父元素中的index
    function _index(el) {
        var index = 0;

        if (!el || !el.parentNode) {
            return -1;
        }
        //previousElementSibling属性返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。
        while (el && (el = el.previousElementSibling)) {
            //console.log(el);
            index++;
        }

        return index;
    }

    function _animate(prevRect, target) {
        var ms = 300;

        if (ms) {
            var currentRect = target.getBoundingClientRect();
           //nodeType 属性返回以数字值返回指定节点的节点类型。1=元素节点  2=属性节点
            if (prevRect.nodeType === 1) {
                prevRect = prevRect.getBoundingClientRect();
            }
            _css(target, 'transition', 'none');
            _css(target, 'transform', 'translate3d(' +
                (prevRect.left - currentRect.left) + 'px,' +
                (prevRect.top - currentRect.top) + 'px,0)'
            );

            target.offsetWidth; // 触发重绘
            //放在timeout里面也可以
            // setTimeout(function() {
            //     _css(target, 'transition', 'all ' + ms + 'ms');
            //     _css(target, 'transform', 'translate3d(0,0,0)');
            // }, 0);
            _css(target, 'transition', 'all ' + ms + 'ms');
            _css(target, 'transform', 'translate3d(0,0,0)');

            clearTimeout(target.animated);
            target.animated = setTimeout(function() {
                _css(target, 'transition', '');
                _css(target, 'transform', '');
                target.animated = false;
            }, ms);
        }
    }
    //给元素添加style
    function _css(el, prop, val) {
        var style = el && el.style;

        if (style) {
            if (val === void 0) {
                //使用DefaultView属性可以指定打开窗体时所用的视图
                if (document.defaultView && document.defaultView.getComputedStyle) {
                    val = document.defaultView.getComputedStyle(el, '');
                } else if (el.currentStyle) {
                    val = el.currentStyle;
                }

                return prop === void 0 ? val : val[prop];
            } else {
                if (!(prop in style)) {
                    prop = '-webkit-' + prop;
                }

                style[prop] = val + (typeof val === 'string' ? '' : 'px');
            }
        }
    }
</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/690153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Makefile】解析Makefile:驾驭自动编译的力量

Makefile简介 一个工程中的源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪些文件需要后编译&#xff0c;哪些文件需要重新编译&#xff0c;甚至于进行更复杂的…

你如何理解 JS 的继承?

在JavaScript中&#xff0c;继承是一种机制&#xff0c;允许一个对象&#xff08;子类&#xff09;从另一个对象&#xff08;父类&#xff09;继承属性和方法。这使得子类可以共享父类的功能&#xff0c;并有能∧自身定义新的功能。 JavaScript中的继承通过原型链实现。 具体来…

JavaWeb开发(前端Web开发)

文章目录 前言一、初识Web1.Web开发-介绍2.初识Web前端3.Web标准 二、HTML1.HTML快速入门2.VS Code开发工具3.基础标签&样式4.表格标签5.表单标签 三、JavaScript1.JS-介绍2.JS-引入方式3.JS-基础语法3.1.JS-基础语法-书写语法3.2.JS-基础语法-变量3.2.JS-基础语法-数据类型…

面向Java开发者的ChatGPT提示词工程(7)

在如今信息爆炸的时代&#xff0c;我们面临着海量的文字信息&#xff0c;很难抽出足够的时间去阅读所有感兴趣的内容。然而&#xff0c;大语言模型为我们提供了一种有效的解决方案&#xff1a;通过自动文本摘要&#xff0c;帮助我们快速获取文章的核心内容。这种技术已经被广泛…

vue2 h5开发前进刷新后退缓存实现

vue2 h5开发前进刷新后退缓存实现 在store定义变量 const state {includedComponents: [] }const mutations {includedComponents (state, data) {state.includedComponents data} }在app.vue&#xff08;我这里主要在layout.vue修改&#xff09;使用 keep-alive :include…

使用Microsoft.Office.Interop.PowerPoin遥控PPT

Microsoft.Office.Interop.PowerPoin操作PPT 主窗体&#xff0c;填写ppt路径&#xff0c;打开ppt打开ppt后&#xff0c;可用代码操作ppt可获取每页PPT截图&#xff0c;并获取对应小节名称&#xff0c;备注等代码下载地址联系qq 主窗体&#xff0c;填写ppt路径&#xff0c;打开p…

四.图像处理与光学之3A的 AE

五.图像处理与光学之3A的 AE 3A 是Camera ISP 控制算法的一个重要组成部分,通常分为自动曝光(AE)、自动聚焦(AF)、自动白平衡(AWB)三个组件。 5.0 概述自动曝光(Auto Exposure) 自动曝光算法可以理解为一个伺服系统,它不断监控ISP生成的每一帧图像的曝光状态,如果发现采…

C# Winform小程序:局域网设置NTP服务器、实现时间同步

设置NTP服务器&#xff1a; NTP是网络时间协议(Network Time Protocol)&#xff0c;它是用来同步网络中各个计算机的时间的协议。 局域网不能连接Internet&#xff0c;可以设置一台计算机为NTP服务器。 依次点击&#xff1a;开始---运行---regedit&#xff0c;进入注册表&am…

晶体管放大器结构原理图解

功率放大器的作用是将来自前置放大器的信号放大到足够能推动相应扬声器系统所需的功率。就其功率来说远比前置放大器简单&#xff0c;就其消耗的电功率来说远比前置放大器为大&#xff0c;因为功率放大器的本质就是将交流电能"转化"为音频信号&#xff0c;当然其中不…

JAVA 正则表达式 及 案例

JAVA 正则表达式 及 案例 目录 JAVA 正则表达式 及 案例1.正则表达式Regex1.1 概述1.2 常见语法1.3 String提供了支持正则表达式的方法1.4 练习&#xff1a;测试输入身份证号 1.正则表达式Regex 1.1 概述 正确的字符串格式规则。 常用来判断用户输入的内容是否符合格式的要求…

chatgpt赋能python:为什么在写Python代码时需要注意空格的使用

为什么在写Python代码时需要注意空格的使用 作为一门高效、易读且简单的编程语言&#xff0c;Python在软件开发领域中得到了越来越广泛的应用。然而&#xff0c;在Python的编码过程中&#xff0c;空格的使用可能会带来一些难以预料到的问题。为了避免这些问题&#xff0c;我们…

Redis【实战篇】---- 商户查询缓存

Redis【实战篇】---- 商户查询缓存 1. 什么是缓存&#xff1f;1. 为什么要使用缓存2. 如何使用缓存 2. 添加商户缓存1. 缓存模型和思路2. 代码如下 3. 缓存更新策略1. 数据库缓存不一致解决方案2. 数据库和缓存不一致采用什么方案 4. 实现商铺和缓存与数据库双写一致5. 缓存穿透…

Linux系统编程:详解环境变量

目录 一. 环境变量的基本概念 1.1 什么是环境变量 1.2 环境变量的功能测试 二. 与环境变量相关的操作 三. 环境变量的组织方式 四. 通过代码获取环境变量的值 五. 总结 一. 环境变量的基本概念 1.1 什么是环境变量 环境变量是用于指定操作系统相关参数的、全局的变量。…

大语言模型 -- 部署LaWGPT模型记录

模型介绍&#xff1a; 该系列模型在通用中文基座模型&#xff08;如 Chinese-LLaMA、ChatGLM 等&#xff09;的基础上扩充法律领域专有词表、大规模中文法律语料预训练&#xff0c;增强了大模型在法律领域的基础语义理解能力。在此基础上&#xff0c;构造法律领域对话问答数据…

SpringBoot——2.7.3版本整合Swagger3

前言 Swagger2&#xff08;基于openApi3&#xff09;已经在17年停止维护了&#xff0c;取而代之的是 sagger3&#xff08;基于openApi3&#xff09;&#xff0c;而国内几乎没有 sagger3使用的文档&#xff0c;百度搜出来的大部分都是swagger2的使用&#xff0c;这篇文章将介绍…

存量时代,CRM系统如何赋能企业客户关系管理

如何发掘和吸引新客户、如何维系现有客户、如何推动业务增长&#xff0c;一直是众多公司运营管理中时常要面对的关键问题。尤其在数字化时代&#xff0c;用户获取信息的渠道越来越丰富&#xff0c;企业的获客渠道也在日益增多&#xff0c;面对每天的海量数据&#xff0c;企业该…

【无线传感器】使用 MATLAB和 XBee连续监控温度传感器无线网络研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【MOOC 测验】第3章 运输层

1​、在 ISO/OSI 参考模型中&#xff0c;对于运输层描述正确的有&#xff08; &#xff09; A. 为传输数据选择数据链路层所提供的最合适的服务B. 为系统之间提供面向连接的数据传输服务C. 可以提供端到端的差错恢复和流量控制&#xff0c;实现可靠的数据传输D. 提供路由选择…

TP composer 新创建一个vendor2,作为新库下载目录

站点目录新建一个vendor2文件夹&#xff1a; 在里面新建一个 composer.json 文件&#xff1a;(只写一个花括号就行) {} 然后这个vendor2目录里&#xff0c;使用宝塔终端执行&#xff1a; composer require zoujingli/ip2region 这样&#xff0c;vendor2目录里就会再多出 v…

AI大模型应用时代,如何通过数据“造好品,卖好品”?

在数字化时代的浪潮中&#xff0c;品牌营销正面临着前所未有的挑战和机遇。随着技术的迅猛发展&#xff0c;消费者的行为和期望也在不断演变。 新的市场环境下&#xff0c;消费者的需求和购买行为发生了哪些变化&#xff1f; 数码家电转战社媒平台&#xff0c;竞争白热化如…