前端模拟排序动画

转载自携程前端模拟排序动画

昨天晚上作携程的笔试,第三道题是让模拟一个排序的步骤,也就是将排序的过程以动画的形式表现出来。javascript

即这种效果 css

首先赞一下携程的这道题目,这才是前端该作的题目,既有意思,又考察了排序算法,还考察了部分动画及 dom 操做。话很少说,分析一下这道题目。

首先是页面基本结构html

前端

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>排序动画演示</title> </head> <body> <div class="container">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
复制代码
复制代码<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> 复制代码</body> </html> 复制代码复制代码

而后给待排序元素加个样式java

.container{
    text-align:center;
}
.sort{
    position:absolute;
    width:50px;
    height:50px;
    line-height:50px;
    border:1px solid black;
    transition:1s; 
}
复制代码复制代码

为何绝对定位呢,首先绝对定位可让元素脱离文档流,可以尽可能减小重排,并且绝对定位的位置方便计算,因此这里采用绝对定位,固然 fixed 也是能够的。而后最重要的就是动画的持续时间设置为 1snode

而后首先将待排序元素输出到界面git

var arr = [5,4,8,9,6,5,4,12,3,6,7,8,56];
var container = document.querySelector('.container');
var fragment = document.createDocumentFragment(); // 建立文档片断,尽可能减小重绘和重排
var len = arr.length;
for(let i = 0; i < len; i++ ){
    var node = document.createElement('div');
    node.className = 'sort';
    node.id = i; // 这个后面移动位置的时候须要用到
    node.style.left = i * 60 + 'px';
    fragment.append(node);
}
container.append(fragment);
复制代码复制代码

至此,把待排序元素先输出到页面上了。 github

而后开始处理排序,这里采用冒泡排序,正常的冒泡排序结构是这样的

for(let i = 0; i < len; i++){
    for(let j = 0; j < len - i; j++){
    	if(arr[j] > arr[j+1]){
    	    // 这里使用了 ES6 的解构赋值,即交换两个元素的值
    		[arr[j],arr[j+1]] = [arr[j+1],arr[j]];
    		// 也能够这样
    		/* var temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; */
    	}
    }
}
复制代码复制代码

解构赋值仍是很好用的,推荐使用结构赋值算法

那么咱们要实现冒泡排序的动画该怎么办呢。app

首先咱们要获取交换的两个元素距离左边长度,而后交换这两个元素的位置,还记得咱们以前给元素赋值了 ID 吗,咱们能够经过 ID 来找到这两个元素。

var x = document.getElementById(j)	
var y = document.getElementById(j+1);
// 这里一样采用解构赋值
[x.style.left,y.style.left] = [y.style.left,x.style.left];
// 记得 id 也要交换
[x.id,y.id]=[y.id,x.id];
复制代码复制代码

至此,咱们作完了该作的一切,可是直接把这段代码加入到冒泡排序里面的话那咱们直接看到的就是排序完成的效果了,看不到中间的过程,那要怎么样才能看到排序的过程呢,这个时候咱们能够使用 setTimeout。

冒泡部分的代码以下

var time = 1; for(let i = 0; i < len; i++){ for(let j = 0; j < len - i; j++){ if(arr[j] > arr[j+1]){ [arr[j],arr[j+1]] = [arr[j+1],arr[j]]; setTimeout(function(){ var x = document.getElementById(j) var y = document.getElementById(j+1); [x.style.left,y.style.left] = [y.style.left,x.style.left]; [x.id,y.id] = [y.id,x.id]; },time * 1000) time++; }
}
复制代码
复制代码} 复制代码} 复制代码复制代码

time 是为了让每次的效果都显示出来,若是只是 1000 的话,那么这个动画 1s 以内就会完成,若是不清楚能够复习一下事件循环的相关知识。

至此,代码结束

预览地址

所有代码

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>排序</title> <style> .container{ text-align: center; } .sort{ transition: 1s; height: 50px; width: 50px; border: 1px solid black; line-height: 50px; position: absolute; }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
复制代码
复制代码</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span> 复制代码</head> <body> <div class="container"> </div> <script> var arr = [5,4,8,9,6,5,4,12,3,6,7,8,56]; var container = document.querySelector('.container'); var fragment = document.createDocumentFragment(); var len = arr.length; for(let i = 0; i < len;i++){ var temp = document.createElement('div'); temp.className = 'sort'; temp.style.left = i*60 +'px'; temp.id = i; temp.innerHTML = arr[i]; fragment.append(temp); } container.append(fragment); var time = 1; for(let i = 0; i < len; i++){ for(let j = 0; j < len - i; j++){ if(arr[j] > arr[j+1]){ [arr[j],arr[j+1]] = [arr[j+1],arr[j]]; setTimeout(function(){ var x = document.getElementById(j) var y = document.getElementById(j+1); [x.style.left,y.style.left] = [y.style.left,x.style.left]; [x.id,y.id] = [y.id,x.id]; },time * 1000) time++; } } } </script> </body> </html> 复制代码复制代码
相关文章
相关标签/搜索