效果

原理详解

链接

1.beforeUpdate 获取first 变化前位置 (以id建立map映射)
2.updated 获取变化后位置 last
3.禁用transition并transform元素回初始位置
4.异步恢复transition 并取消 transform

代码

<template><div ref="container"><div style="display: flex"><div style="width:400px"><!--仅展示三级数据,若需递归自行修改--><div class="item" :id="i.value" v-for="i in locArr" :key="i.value"><div>{{i.label}}</div><div class="item" :id="j.value" v-for="j in i.children" :key="j.value"><div>{{j.label}}</div><div class="item" :id="k.value" v-for="k in j.children" :key="k.value"><div>{{k.label}}</div></div></div></div></div><div style="padding: 10px"><button @click="shuffle">重新随机数据</button><button @click="shuffleOne">打乱一级顺序</button><button @click="shuffleTwo">打乱二级顺序</button></div></div></div>
</template><script>
/*
1.beforeUpdate 获取first 变化前位置 (以id建立map映射),
2.updated 获取变化后位置 last ,
3.禁用transition并transform元素回初始位置,
4.异步恢复transition 并取消 transform
*//*** 乱序数组*/
Array.prototype.shuffle = function () {let input = this;for (let i = input.length - 1; i >= 1; i--) {let ri = ~~(Math.random() * (i + 1));input[i] = [input[ri], input[ri] = input[i]][0];}return input;
};/*** 随机多级数据* @param root* @param len* @param level*/
const treeOptions = ({ root = '0', len = 40, level = 4 }) => {let levelPoolLen = level, originPoolLen = len - levelPoolLen//创建 level 个 LevelPool ,并为每个 LevelPool 初始化一个元素let levelPool = []for (let i = 1; i <= levelPoolLen; i++) {levelPool.push([{ id: '', parentId: root, label: '', value: '' }])}//初始化指定数量的元素并随机丢入 LevelPool 中for (let i = 0; i < originPoolLen; i++) {let currLevel = ~~(Math.random() * level)levelPool[currLevel].push({ id: '', parentId: root, label: '', value: '' })}let nextId = 0//由前到后依次遍历LevelPool,遍历本级池中各项并随机从前一级池中选取一项作为当前项的父级for (let i = 0, item; (item = levelPool[0][i]) != null; i++) {item.id = ++nextIditem.parentId = rootitem.label = `label${item.id}`item.value = `value${item.id}`item.level = 0}for (let i = 1; i < levelPoolLen; i++) {let prevLevelPool = levelPool[i - 1]let prevLevelPoolLen = prevLevelPool.lengthfor (let j = 0, item; (item = levelPool[i][j]) != null; j++) {//随机父节点let parent = prevLevelPool[~~(Math.random() * prevLevelPoolLen)]if (!parent.children) {parent.children = []}item.id = `${parent.id}-${parent.children.length}`item.parentId = parent.iditem.label = `label${item.id}`item.value = `value${item.id}`item.level = iparent.children.push(item)}}//将一级levelPool合并输出return levelPool[0]
}let firstMap = [], last = []
export default {name: "FLIP",data() {return {locArr: treeOptions({ level: 3, len: 40 })}},beforeUpdate() {this.$refs.container.querySelectorAll('.item').forEach(d => firstMap[d.id] = d.getBoundingClientRect())},updated() {let lastRect, firstRect, transX, transY, $lastNodes = this.$refs.container.querySelectorAll('.item')$lastNodes.forEach(d => {lastRect = d.getBoundingClientRect()firstRect = firstMap[d.id]if (firstRect) {transX = firstRect.left - lastRect.lefttransY = firstRect.top - lastRect.topd.style.transition = 'none'd.style.transform = `translate3D(${transX}px,${transY}px,0) `}})setTimeout(_ => {$lastNodes.forEach(d => {d.style.transition = ''d.style.transform = ''})})},methods: {shuffle() {// this.locArr[1].children.push(  this.locArr.shift())this.locArr = treeOptions({ level: 3, len: 40 })},shuffleOne() {this.locArr = [...this.locArr.shuffle()]},shuffleTwo() {const vm = thisthis.locArr.forEach((d, index) => {if (d.children) {d.children = [...d.children.shuffle()]}})}}
}
</script><style scoped>.item {transition: all 1s;margin-left: 20px;}.item>div:not(.item){padding:5px;border-radius:2px;background: #fff;box-shadow: #999999 2px 2px 5px 1px;}button{display: block;margin: 10px;cursor: pointer;}
</style>

列表排序应用FLIP动画(vue)相关推荐

  1. 28.Vue列表排序

    27.Vue列表过滤_爱米酱的博客-CSDN博客目录1.使用watch属性实现列表过滤2.使用计算属性实现列表过滤3.总结这一小节我们来讲一下Vue的列表过滤,那么想要完成列表过滤就需要有两个关键的步 ...

  2. Vue 知识点:列表排序

    Vue 知识点:列表排序 <div id="root"><h2>人员列表</h2><input type="text" ...

  3. 巧用order实现列表排序

    前言 近些年,随着 web 应用的蓬勃发展,前端所需要承载的业务需求与开发任务越来越多.一些曾经第一反应是 "调一下后端接口就完事儿" 的任务,随着 数据量 的提升以及对 用户体验 ...

  4. 舔狗是这样实现列表过滤和列表排序滴

    如果你是一个舔狗,又不会写舔狗日记,又恰好会一点点Vue的话,恭喜你这篇舔狗拯救手册可以帮助你顺利处到 {} 干活干活!首先搭建好Vue基本模板 <body><div id=&quo ...

  5. FLIP 动画实现多维网格的过渡

    FLIP 动画实现多维网格的过渡 Demo地址:https://jsfiddle.net/chrzmzxv/ <!DOCTYPE html> <html> <head l ...

  6. FLIP动画实现思路

    如果让你实现下面的这种动画效果你会怎么做? ​ 可能很多人第一想法就是使用绝对定位进行布局,当顺序发生变化后,计算出变化后的位置,然后通过动画过渡到指定位置.这是一种很常见的实现方式,但存在几个问题: ...

  7. python制作酷炫动画_厉害了!Python+matplotlib制作8个排序算法的动画

    1 算法的魅力 深刻研究排序算法是入门算法较为好的一种方法,现在还记得4年前手动实现常见8种排序算法,通过随机生成一些数据,逐个校验代码实现的排序过程是否与预期的一致,越做越有劲,越有劲越想去研究,公 ...

  8. Python学习教程实用技法:通过公共键对字典列表排序—itemgetter

    Python学习教程实用技法:通过公共键对字典列表排序-itemgetter 前言:我们有一个字典列表,想根据一个或多个字典中的值对列表进行排序. 利用operator模块中的itemgetter函数 ...

  9. 利用jQuery对无序列表排序 http://www.apkbus.com/android-80639-1-1.html

    利用jQuery对无序列表排序的原理是:获取到无序列表中的所有列表项,并转成数组形式,使用JavaScript函数对其进行排序后再次输出.其中使用到的jQuery函数有ready().get().te ...

最新文章

  1. alternate端口什么意思_宽带光信号闪红灯是什么意思?
  2. RRDTool 存储原理简介——基于时间序列的环型数据库
  3. spring4-3-AOP-面向切面编程
  4. Activiti 初步学习
  5. S/4HANA extension field search的SQL语句是在什么地方生成的
  6. 重启php-fpm的方法
  7. dom属性和html属性_HTML属性
  8. 电脑开启防火墙后ping不通 及 开启防火墙后,不能远程的解决办法
  9. STM32之DAC原理
  10. 背包——01背包Bone Collector(hdu2602)
  11. socket android用法,Android NDK中socket的用法以及注意事项分析
  12. linux gpsd 授时原理,app/ntp/gps/README.md · 王者归来/ITTS - Gitee.com
  13. 什么是低信噪比图像及处理方法
  14. n倍角公式的行列式形式与证明
  15. 集团企业智慧建造管理平台劳务管理系统
  16. 每日一词20190306——经纬度(longitude and latitude)
  17. [基础]tfcenter搭建个人服务器
  18. blob:https视频下载m3u8视频在线下载
  19. arduino期末考试题
  20. php在线编辑gif图片,gif动态图片制作,在线制作 GIF动画工具

热门文章

  1. Android之自定义属性
  2. Python 操作 MongoDB
  3. 句子录音打分代码参考
  4. C++学习之路 | PTA乙级—— 1061 判断题 (15 分)(精简)
  5. java web swing 教程_好程序员Java教程解读什么是swing
  6. 【加解密学习笔记:第一天】操作系统基础知识
  7. JAVA入门级教学之(参数传递)
  8. mysql 缓解竞争热点_MySQL优化之缓存优化
  9. python r语言 作图_生物医学绘图,Python 并不比R语言差
  10. C语言编程日志,用C语言打印日志(Log)