携程前端模拟排序动画

发布于 2023-04-16 13:10:09 字数 4200 浏览 87 评论 0

昨天晚上做携程的笔试,第三道题是让模拟一个排序的步骤,也就是将排序的过程以动画的形式表现出来。首先赞一下携程的这道题目,这才是前端该做的题目,既有意思,又考察了排序算法,还考察了部分动画及 dom 操作。话不多说,分析一下这道题目。

首先是页面基本结构

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>排序动画演示</title>
</head>
<body>
	<div class="container"></div>
</body> </html>

然后给待排序元素加个样式

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

为什么绝对定位呢,首先绝对定位可以让元素脱离文档流,能够尽量减少重排,而且绝对定位的位置方便计算,所以这里采用绝对定位,当然 fixed 也是可以的。然后最重要的就是动画的持续时间设置为 1s

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

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);

至此,把待排序元素先输出到页面上了。然后开始处理排序,这里采用冒泡排序,正常的冒泡排序结构是这样的。

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;
    		*/
    	}
    }
}

解构赋值还是很好用的,推荐使用结构赋值,那么我们要实现冒泡排序的动画该怎么办呢?首先我们要获取交换的两个元素距离左边长度,然后交换这两个元素的位置,还记得我们之前给元素赋值了 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;
		}
</style>
</head>
<body>
<div>
</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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

孤檠

暂无简介

0 文章
0 评论
478 人气
更多

推荐作者

亽野灬性zι浪

文章 0 评论 0

少年亿悲伤

文章 0 评论 0

南七夏

文章 0 评论 0

qq_EJoXxu

文章 0 评论 0

17780639550

文章 0 评论 0

萌逼全场

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文