使用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编写排序算法
交换排序 === 冒泡排序,快速排序 插入排序 ===直接插入排序,希尔排序 选择排序 === 简单选择排序,堆排序 归并排序 基数排序 冒泡排序 要点 冒泡排序是一种交换排序. 什么是交换排序呢? ...
随机推荐
- php第一次实验个人博客网站的设计编写①
先上效果图: 网页代码:index.html <!DOCTYPE html> <html lang="en"> <head> <m ...
- github ations 入门使用
在使用之前,我们了解一下什么是 Github Actions. 在 GitHub Actions 的仓库中自动化.自定义和执行软件开发工作流程. 您可以发现.创建和共享操作以执行您喜欢的任何作业(包括 ...
- Django显示本地图片,注意事项
1.在url.py文件中的配置 导入相关的库,在Python2.0后,要用re_path from django.urls import path,re_path from django.views. ...
- 攻防世界-MISC:glance-50
这是攻防世界MISC高手进阶区的题目,题目如下: 点击下载附件一,得到一张GIF动图如下 找个网站给分离一下,将gif分离为图片,共201张,然后拼接在一起即可得到flag 所以这道题的flag如下: ...
- XCTF练习题---WEB---backup
XCTF练习题---WEB---backup flag:Cyberpeace{855A1C4B3401294CB6604CCC98BDE334} 解题步骤: 1.观察题目,打开场景 2.打开以后发现是 ...
- PHP 运行 mkdir() Permission Denied 的原因
使用lamp,在上传文件时,PHP执行 mkdir($path) , 出现没有权限的错误. 解决: 本次使用的时yii框架,所以首先确保 是apache的用户对web目录有权限,然后再给此用户加 r ...
- 各种查找算法的选用分析(顺序查找、二分查找、二叉平衡树、B树、红黑树、B+树)
目录 顺序查找 二分查找 二叉平衡树 B树 红黑树 B+树 参考文档 顺序查找 给你一组数,最自然的效率最低的查找算法是顺序查找--从头到尾挨个挨个遍历查找,它的时间复杂度为O(n). 二分查找 而另 ...
- 在GO中调用C源代码#基础篇1
开坑说明 最近在编写客户端程序或与其他部门做功能集成时多次碰到了跨语言的sdk集成,虽说方案很多诸如rpc啊,管道啊,文件io啊,unix socket啊之类的不要太多,但最完美的基础方式还是让程序与 ...
- 你不知道的JS 中——yield
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Python技法:实用运维脚本编写(进程/文件/目录操作)
Python在很大程度上可以对shell脚本进行替代.笔者一般单行命令用shell,复杂点的多行操作就直接用Python了.这篇文章就归纳一下Python的一些实用脚本操作. 1. 执行外部程序或命令 ...