前端模擬排序動畫

轉載自攜程前端模擬排序動畫

昨天晚上作攜程的筆試,第三道題是讓模擬一個排序的步驟,也就是將排序的過程以動畫的形式表現出來。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> 複製代碼複製代碼
相關文章
相關標籤/搜索