FLIP动画做拖拽排序效果

news2024/11/15 11:13:21

先来看效果
在这里插入图片描述

index.html文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./index.css" />
  </head>
  <body>
    <div class="list">
      <div draggable="true" class="list-item">1</div>
      <div draggable="true" class="list-item">2</div>
      <div draggable="true" class="list-item">3</div>
      <div draggable="true" class="list-item">4</div>
      <div draggable="true" class="list-item">5</div>
    </div>
    <script src="./Flip.js"></script>
    <script src="./index.js"></script>
  </body>
</html>

index.css文件

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.list {
  width: 500px;
}

.list-item {
  margin: 5px 0;
  padding: 0 20px;
  line-height: 40px;
  height: 40px;
  background: linear-gradient(to right, #267871, #136a8a);
  color: #fff;
  cursor: move;
  user-select: none;
  border-radius: 5px;
}
.list-item.moving {
  background: transparent;
  color: transparent;
  border: 1px dashed #ccc;
}

index.js文件

const list = document.querySelector('.list');
let sourceNode; // 当前正在拖动的是哪个元素
let flip;
list.ondragstart = (e) => {
  setTimeout(() => {
    e.target.classList.add('moving');
  }, 0);
  sourceNode = e.target;
  e.dataTransfer.effectAllowed = 'move';
  flip = new Flip(list.children, 0.3);
};
list.ondragover = (e) => {
  e.preventDefault();
};
list.ondragenter = (e) => {
  e.preventDefault();
  if (e.target === list || e.target === sourceNode) {
    return;
  }
  const children = Array.from(list.children);
  const sourceIndex = children.indexOf(sourceNode);
  const targetIndex = children.indexOf(e.target);
  if (sourceIndex < targetIndex) {
    list.insertBefore(sourceNode, e.target.nextElementSibling);
  } else {
    list.insertBefore(sourceNode, e.target);
  }
  flip.play();
};

list.ondragend = (e) => {
  e.target.classList.remove('moving');
};

Flip.js文件

const Flip = (function () {
  class FlipDom {
    constructor(dom, duration = 0.5) {
      this.dom = dom;
      this.transition =
        typeof duration === 'number' ? `${duration}s` : duration;
      this.firstPosition = {
        x: null,
        y: null,
      };
      this.isPlaying = false;
      this.transitionEndHandler = () => {
        this.isPlaying = false;
        this.recordFirst();
      };
    }

    getDomPosition() {
      const rect = this.dom.getBoundingClientRect();
      return {
        x: rect.left,
        y: rect.top,
      };
    }

    recordFirst(firstPosition) {
      if (!firstPosition) {
        firstPosition = this.getDomPosition();
      }
      this.firstPosition.x = firstPosition.x;
      this.firstPosition.y = firstPosition.y;
    }

    *play() {
      if (!this.isPlaying) {
        this.dom.style.transition = 'none';
        const lastPosition = this.getDomPosition();
        const dis = {
          x: lastPosition.x - this.firstPosition.x,
          y: lastPosition.y - this.firstPosition.y,
        };
        if (!dis.x && !dis.y) {
          return;
        }
        this.dom.style.transform = `translate(${-dis.x}px, ${-dis.y}px)`;
        yield 'moveToFirst';
        this.isPlaying = true;
      }

      this.dom.style.transition = this.transition;
      this.dom.style.transform = `none`;
      this.dom.removeEventListener('transitionend', this.transitionEndHandler);
      this.dom.addEventListener('transitionend', this.transitionEndHandler);
    }
  }

  class Flip {
    constructor(doms, duration = 0.5) {
      this.flipDoms = [...doms].map((it) => new FlipDom(it, duration));
      this.flipDoms = new Set(this.flipDoms);
      this.duration = duration;
      this.flipDoms.forEach((it) => it.recordFirst());
    }

    addDom(dom, firstPosition) {
      const flipDom = new FlipDom(dom, this.duration);
      this.flipDoms.add(flipDom);
      flipDom.recordFirst(firstPosition);
    }

    play() {
      let gs = [...this.flipDoms]
        .map((it) => {
          const generator = it.play();
          return {
            generator,
            iteratorResult: generator.next(),
          };
        })
        .filter((g) => !g.iteratorResult.done);

      while (gs.length > 0) {
        document.body.clientWidth;
        gs = gs
          .map((g) => {
            g.iteratorResult = g.generator.next();
            return g;
          })
          .filter((g) => !g.iteratorResult.done);
      }
    }
  }

  return Flip;
})();

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

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

相关文章

系统架构设计:1论软件系统建模方法及其应用(试读)

目录 一 软件系统建模方法 1结构化建模 2信息工程建模 3面向对象建模 4功能分解法 5基于构件的开发方法 一 软件系统建模方法 软件建模体现了软件设计的思想&#xff0c;是连接需求和实现的桥梁&#xff0c;用于指导软件的具体实现。软件模型不是软件系统的完备表示&…

【Pytorch模型可视化】Netron可视化pytorch框架下的模型

文章目录 1. 下载Netron2. pth/pt转onnx3. 可视化实现 1. 下载Netron github 下载链接&#xff1a;https://github.com/lutzroeder/Netron 打开上面网页&#xff0c;显示界面中的 Windows&#xff1a;Download 处点击直接下载 .exe 可执行文件。 如果觉得下载麻烦&#xff0c…

常见的通用型项目管理软件推荐

常用项目管理软件有很多。按适合的行业来分&#xff0c;有针对各种垂直行业定制的&#xff0c;也有全行业通用的。从厂商来看&#xff0c;有国外研发的&#xff0c;也有国内厂商的&#xff0c;体现在软件的设计思路不同&#xff0c;上手的手感也很不一样。从体量来看&#xff0…

dom-to-image库是如何将html转换成图片的

dom-to-image库可以帮你把dom节点转换为图片&#xff0c;它的核心原理很简单&#xff0c;就是利用svg的foreignObject标签能嵌入html的特性&#xff0c;然后通过img标签加载svg&#xff0c;最后再通过canvas绘制img实现导出&#xff0c;好了&#xff0c;本文到此结束。 另一个…

SpringBoot之使用Redis和注解实现接口幂等性

文章目录 1 接口幂等性1.1 概念1.2 实现思路1.3 代码实现1.3.1 pom1.3.2 JedisUtil1.3.3 自定义注解ApiIdempotent1.3.4 ApiIdempotentInterceptor拦截器1.3.5 TokenServiceImpl1.3.6 TestApplication 1.4 测试验证1.4.1 获取token的控制器TokenController1.4.2 TestController…

[ICCV-23] DeformToon3D: Deformable Neural Radiance Fields for 3D Toonification

pdf | code 将3D人脸风格化问题拆分为几何风格化与纹理风格化。提出StyleField&#xff0c;学习以风格/ID为控制信号的几何形变残差&#xff0c;实现几何风格化。通过对超分网络引入AdaIN&#xff0c;实现纹理风格化。由于没有修改3D GAN空间&#xff0c;因此可以便捷实现Edit…

Matlab导入log(或txt)文件,提取数据或其他信息

导入log&#xff08;或txt)文件 先上代码&#xff1a; clc; clear; %数据导入 file1fullfile(文件路径, test1.log); % 导入文件test1.log f1fopen(file1); dt1textscan(f1,%s); %采用textscan 读取数据 %得到的dt1是元胞数组格式比如&#xff1a;有如下内容文件 导入…

java案例20:库存管理系统

思路&#xff1a; 像商场、超市这样的地方&#xff0c;都需要有自己的库房&#xff0c;并且库房商品的库存变化有专人记录&#xff0c;这样才能保证商城和超市正常运转编写程序&#xff0c;模拟库存管理系统 该系统主要包括系统首页、商品入库、商品显示和删除商品功能 每个功…

spark-03

RDD是抽象概念&#xff0c;分区是物理概念

区分 关系代数中的笛卡尔积、等值连接、自然连接(图文界面)

目录 前言1. 笛卡尔积2. 等值连接3. 自然连接 前言 深度卷积的笛卡尔积、软考高级等常出现类似这种知识点 归根到底是关系代数的数学知识 今天就专门区分一下 概念定义笛卡尔积两个关系R和S进行操作&#xff0c;产生的关系中元组个数为两个关系中元组个数之积等值联接&#…

C++QT-day3

#include <iostream> /*设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、* 指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;* 类中包含私有成员:成绩、Per类对象p1&#xff0c;* 设计这两个类的构造函数、析构函数和拷贝构造函数。*/ using namespac…

机器学习1:k 近邻算法

k近邻算法&#xff08;k-Nearest Neighbors, k-NN&#xff09;是一种常用的分类和回归算法。它基于一个简单的假设&#xff1a;如果一个样本的k个最近邻居中大多数属于某一类别&#xff0c;那么该样本也很可能属于这个类别。 k近邻算法的步骤如下&#xff1a; 输入&#xff1a…

设计模式 - 行为型模式考点篇:模板方法模式(概念 | 案例实现 | 优缺点 | 使用场景)

目录 一、行为型模式 1.1、模板方法模式 1.1.1、概念 1.1.2、案例实现 1.1.3、优缺点 1.1.4、使用场景 一、行为型模式 一句话概括行为型模式 行为型模式&#xff1a;类或对象间如何交互、如何划分职责&#xff0c;从而更好的完成任务. 1.1、模板方法模式 1.1.1、概念 …

COCI 2021-2022 #1 - Volontiranje 题解

题目大意 让你求最多有多少个不相交的最长上升子序列。 思路 我们可以将数 a i a_i ai​ 看成一个点 ( i , a [ i ] ) (i,a[i]) (i,a[i])&#xff0c;于是我们可以按照 x x x 递增 y y y 递减考虑分层。 分层的方法就是从 1 1 1 到当前点的 LIS 即为其所在层数。 此时…

Spring源码解析——IOC之bean 的初始化

正文 一个 bean 经历了 createBeanInstance() 被创建出来&#xff0c;然后又经过一番属性注入&#xff0c;依赖处理&#xff0c;历经千辛万苦&#xff0c;千锤百炼&#xff0c;终于有点儿 bean 实例的样子&#xff0c;能堪大任了&#xff0c;只需要经历最后一步就破茧成蝶了。…

Git 学习笔记 | Git 分支

Git 学习笔记 | Git 分支 Git 学习笔记 | Git 分支分支的概念为什么要使用分支&#xff1f;常用指令 Git 学习笔记 | Git 分支 分支的概念 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来&#xff0c;避免影响开发主线。…

小白网络安全学习手册(黑客技术)

一、网络安全应该怎么学&#xff1f; 1.计算机基础需要过关 这一步跟网安关系暂时不大&#xff0c;是进入it行业每个人都必须掌握的基础能力。 计算机网络计算机操作系统算法与数据架构数据库 Tips:不用非要钻研至非常精通&#xff0c;可以与学习其他课程同步进行。 2.渗透技…

[idekCTF 2022]Paywall - LFI+伪协议+filter_chain

[idekCTF 2022]Paywall 一、解题流程&#xff08;一&#xff09;、分析&#xff08;二&#xff09;、解题 二、思考总结 一、解题流程 &#xff08;一&#xff09;、分析 点击source可以看到源码&#xff0c;其中关键部分&#xff1a;if (isset($_GET[p])) {$article_content…

【C语言】进阶——动态内存管理

一、为什么存在动态内存管理 我们已经掌握的内存开辟方式有&#xff1a; int val 20; //在栈空间开辟四个字节char arr[10] {0}; //在栈空间开辟10个字节的连续空间 但上述开辟空间的方式有两个特点&#xff1a; 空间开辟大小是固定的数组在声明的时候&#xf…

Maven最新版本安装及配置

Maven是一个Java项目管理和构建工具&#xff0c;它可以定义项目结构、项目依赖&#xff0c;并使用统一的方式进行自动化构建&#xff0c;是Java项目不可缺少的工具。 本章我们详细介绍如何使用Maven。 一、Maven是什么&#xff1f; 如果每一个项目都自己搞一套配置&#xf…