使用vue实现排序算法演示动画
缘起
最近做的一个小需求涉及到排序,界面如下所示:
因为项目是使用vue的,所以实现方式很简单,视图部分不用管,本质上就是操作数组,代码如下:
{
// 上移
moveUp (i) {
// 把位置i的元素移到i-1上
let tmp = this.form.replayList.splice(i, 1)
this.form.replayList.splice(i - 1, 0, tmp[0])
},
// 下移
moveDown (i) {
// 把位置i的元素移到i+1上
let tmp = this.form.replayList.splice(i, 1)
this.form.replayList.splice(i + 1, 0, tmp[0])
}
}
这样就可以正常的交换位置了,但是是突变的,没有动画,所以不明显,于是一个码农的自我修养(实际上是太闲)让我打开了vue的网站,看到了这个示例:https://cn.vuejs.org/v2/guide/transitions.html#%E5%88%97%E8%A1%A8%E7%9A%84%E6%8E%92%E5%BA%8F%E8%BF%87%E6%B8%A1
这个示例我已看过多遍,但是一直没用过,这里刚好就是我要的效果,于是一通复制粘贴大法:
<template>
<transition-group name="flip-list" tag="p">
<!--循环生成列表部分,略-->
</transition-group>
</template>
<style>
.flip-list-move {
transition: transform 0.5s;
}
</style>
这样就有交换的过渡效果了,如下:
嗯,舒服了很多,这个需求到这里就完了,但是事情并没有结束,我突然想到了以前看一些算法文章的时候通常会配上一些演示的动画,感觉跟这个很类似,那么是不是可以用这个来实现呢,当然是可以的。
实现算法演示动画
先写一下基本的布局和样式:
<template>
<div class="sortList">
<transition-group name="flip-list" tag="p">
<div
class="item"
v-for="item in list"
:key="item.index"
:style="{height: (item.value / max * 100) + '%'}"
>
<span class="value">{{item.value}}</span>
</div>
</transition-group>
</div>
</template>
<style>
.flip-list-move {
transition: transform 0.5s;
}
</style>
list是要排序的数组,当然是经过处理的,在真正的源数组上加上了唯一的index,因为要能正常过渡的话列表的每一项需要一个唯一的key:
const arr = [10, 43, 23, 65, 343, 75, 100, 34, 45, 3, 56, 22]
export default {
data () {
return {
list: arr.map((item, index) => {
return {
index,
value: item
}
})
}
}
}
max是这个数组中最大的值,用来按比例显示高度:
{
computed: {
max () {
let max = 0
arr.forEach(item => {
if (item > max) {
max = item
}
})
return max
}
}
}
其他样式可以自行发挥,显示效果如下:
简约而不简单~,现在万事俱备,只欠让它动起来,排序算法有很多,但是本人比较菜,所以就拿冒泡算法来举例,最最简单的冒泡排序算法如下:
{
mounted(){
this.bubbleSort()
},
methods: {
bubbleSort() {
let len = this.list.length
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (this.list[j] > this.list[j + 1]) { // 相邻元素两两对比
let tmp = this.list[j] // 元素交换
this.$set(this.list, j, this.list[j + 1])
this.$set(this.list, j + 1, tmp)
}
}
}
}
}
}
但是这样写它是不会动的,瞬间就给你排好了:
试着加个延时:
{
mounted () {
setTimeout(() => {
this.bubbleSort()
}, 1000)
}
}
刷新看效果:
有动画了,不过这种不是我们要的,我们要的应该是下面这样的才对:
所以来改造一下,因为for循环是只要开始执行就不会停的,所以需要把两个for循环改成两个函数,这样可以控制每个循环什么时候执行:
{
bubbleSort () {
let len = this.list.length
let i = 0
let j = 0
// 内层循环
let innerLoop = () => {
// 每个内层循环都执行完毕后再执行下一个外层循环
if (j >= (len - 1 - i)) {
j = 0
i++
outLoop()
return false
}
if (this.list[j].value > this.list[j + 1].value) {
let tmp = this.list[j]
this.$set(this.list, j, this.list[j + 1])
this.$set(this.list, j + 1, tmp)
}
// 动画是500毫秒,所以每隔800毫秒执行下一个内层循环
setTimeout(() => {
j++
innerLoop()
}, 800)
}
// 外层循环
let outLoop = () => {
if (i >= len) {
return false
}
innerLoop()
}
outLoop()
}
}
这样就实现了每一步的动画效果:
但是这样不太直观,因为有些相邻不用交换的时候啥动静也没有,不知道当前具体排到了哪两个,所以需要突出当前正在比较交换的两个元素,首先模板部分给当前正在比较的元素加一个类名,用来高亮显示:
<div
:class="{sortingHighlight: sorts.includes(item.index)}"
>
<span class="value">{{item.value}}</span>
</div>
js部分定义一个数组sorts来装载当前正在比较的两个元素的唯一的index值:
{
data() {
return {
sorts: []
}
},
methods: {
bubbleSort () {
// ...
// 内层循环
let innerLoop = () => {
// 每个内层循环都执行完毕后再执行下一个外层循环
if (j >= (len - 1 - i)) {
// 清空数组
this.sorts = []
j = 0
i++
outLoop()
return false
}
// 将当前正在比较的两个元素的index装到数组里
this.sorts = [this.list[j].index, this.list[j + 1].index]
// ...
}
// 外层循环
// ...
}
}
}
修改后效果如下:
最后,再参考刚才别人的示例把已排序的元素也加上高亮:
{
data() {
return {
sorted: []
}
},
methods: {
bubbleSort () {
// ...
// 内层循环
let innerLoop = () => {
// 每个内层循环都执行完毕后再执行下一个外层循环
if (j >= (len - 1 - i)) {
this.sorts = []
// 看这里,把排好的元素加到数组里就ok了
this.sorted.push(this.list[j].index)
j = 0
i++
outLoop()
return false
}
// ...
}
// 外层循环
// ...
}
}
}
最终效果如下:
接下来看一下选择排序,这是选择排序的算法:
{
selectSort() {
for (let i = 0; i < len - 1; i++) {
minIndex = i
for (let j = i + 1; j < len; j++) {
if (this.list[j].value < this.list[minIndex].value) {
minIndex = j
}
}
tmp = this.list[minIndex]
this.$set(this.list, minIndex, this.list[i])
this.$set(this.list, i, tmp)
}
}
}
选择排序涉及到一个当前最小元素,所以需要新增一个高亮:
<div
:class="{minHighlight: min === item.index , sortingHighlight: sorts.includes(item.index), sortedHighlight: sorted.includes(item.index)}"
>
<span class="value">{{item.value}}</span>
</div>
{
data () {
return {
min: 0
}
},
methods: {
selectSort () {
let len = this.list.length
let i = 0; let j = i + 1
let minIndex, tmp
// 内层循环
let innerLoop = () => {
if (j >= len) {
// 高亮最后要交换的两个元素
this.sorts = [this.list[i].index, this.list[minIndex].index]
// 延时是用来给高亮一点时间
setTimeout(() => {
// 交换当前元素和比当前元素小的元素的位置
tmp = this.list[minIndex]
this.$set(this.list, minIndex, this.list[i])
this.$set(this.list, i, tmp)
this.sorted.push(this.list[i].index)
i++
j = i + 1
outLoop()
}, 1000)
return false
}
// 高亮当前正在寻找中的元素
this.sorts = [this.list[j].index]
// 找到比当前元素小的元素
if (this.list[j].value < this.list[minIndex].value) {
minIndex = j
this.min = this.list[j].index
}
setTimeout(() => {
j++
innerLoop()
}, 800)
}
let outLoop = () => {
if (i >= len - 1) {
this.sorted.push(this.list[i].index)
return false
}
minIndex = i
this.min = this.list[i].index
innerLoop()
}
outLoop()
}
}
}
效果如下:
其他的排序也是同样的套路,将for循环或while循环改写成可以控制的函数形式,然后可能需要稍微修改一下显示逻辑,如果你也有打算写排序文章的话现在就可以给自己加上动图展示了!
总结
之前看到这些动图的时候也有想过怎么实现,但是都没有深究,这次业务开发无意中也算找到了其中的一种实现方式,其实核心逻辑很简单,关键是很多时候没有想到可以这么做,这也许是框架带给我们的另一些好处吧。
使用vue实现排序算法演示动画的更多相关文章
- Canvas制作排序算法演示动画
tips: 形象化演示排序算法可以让初学者快速理解,比较好的例子:jun-lu的SortAnimate,旧金山大学的David Galles教授的算法演示课件.最近在看canvas,试着用js+can ...
- JS写的排序算法演示
看到网上有老外写的,就拿起自已之前完成的jmgraph画图组件也写了一个.想了解jmgraph的请移步:https://github.com/jiamao/jmgraph 当前演示请查看:http:/ ...
- 用HTML5实现的各种排序算法的动画比较 及算法小结
用HTML5实现的各种排序算法的动画比较 http://www.webhek.com/misc/comparison-sort/ 几种排序算法效率的比较 来源:http://blog.chinauni ...
- 链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述
关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学 ...
- 用HTML5实现的各种排序算法的动画比較
用HTML5实现的各种排序算法的动画比較 非常有意思,详见: http://www.webhek.com/misc/comparison-sort/
- GDI+学习笔记(九)带插件的排序算法演示器(MFC中的GDI+实例)
带插件的排序算法演示器 请尊重本人的工作成果,转载请留言.并说明转载地址,谢谢. 地址例如以下: http://blog.csdn.net/fukainankai/article/details/27 ...
- http://www.html5tricks.com/demo/jiaoben2255/index.html 排序算法jquery演示源代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...
- 在Object-C中学习数据结构与算法之排序算法
笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...
- 用python编写排序算法
交换排序 === 冒泡排序,快速排序 插入排序 ===直接插入排序,希尔排序 选择排序 === 简单选择排序,堆排序 归并排序 基数排序 冒泡排序 要点 冒泡排序是一种交换排序. 什么是交换排序呢? ...
随机推荐
- Web安全中的常见Session攻击(预测+劫持+固定)
攻击者至少可以通过以下三种方式来获取一个有效的session标识符: 1.预测 2.捕获(劫持) 3.固定 一.会话预测 预测这种方式,也就是攻击者需要猜测出系统中使用的有效的session标识符(P ...
- Java语言学习day17--7月23日
1.面向对象思想2.类与对象的关系3.局部变量和成员变量的关系4.封装思想5.private,this关键字6.随机点名器 ###01面向对象和面向过程的思想 * A: 面向过程与面向对象都是我们编程 ...
- ArcGIS使用技巧(一)——数据存储
新手,若有错误还请指正! 日常接触ArcGIS较多,发现好多人虽然也在用ArcGIS,但一些基础的小技巧并不知道,写下来希望对大家有所帮助. ArcGIS默认的存储数据库是在C盘(图1),不修改存储数 ...
- JS_进阶-遍历对象属性、数组输出、Math、正则表达式匹配
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- netty系列之:netty中的核心MessageToByte编码器
目录 简介 MessageToByte框架简介 MessageToByteEncoder ByteToMessageDecoder ByteToMessageCodec 总结 简介 之前的文章中,我们 ...
- jmeter元件,作用域与优先级
jmeter元件,作用域与优先级 一.jmeter元件 1.配置元件:优先级最高 1.1 重点使用元件:csv数据文件设置.用户定义变量.计数器 2.取样器:根据不同协议来编写请求脚本的元件 2.1 ...
- jQuery与JavaScript与Ajax三者的区别与联系
简单总结: 1.JS是一门 前端语言. 2.Ajax是一门 技术,它提供了异步更新的机制,使用客户端与服务器间交换数据而非整个页面文档,实现页面的局部更新. 3.jQuery是一个 框架,它对JS进行 ...
- 团队Arpha6
队名:观光队 链接 组长博客 作业博客 组员实践情况 黄恒杰 - **过去两天完成了哪些任务 ** - 文字/口头描述 地图功能增加.博客 - 展示GitHub当日代码/文档签入记录 - 接下来的计划 ...
- CNN-Backbone的Pytorch实现
创建日期: 2020-07-04 17:19:39 简介:卷积神经网络非常适合处理图像相关任务,其优势一是权值共享策略,降低了模型复杂度和参数量,本质上也对应着生物视觉神经的感受野.二是其强大的特征提 ...
- p2p-tunnel 打洞内网穿透系列(三)TCP转发访问内网web服务
系列文章 p2p-tunnel 打洞内网穿透系列(一)客户端配置及打洞 p2p-tunnel 打洞内网穿透系列(二)TCP转发访问远程共享文件夹 p2p-tunnel 打洞内网穿透系列(三)TCP转发 ...