js实现冒泡排序的动画

本文介绍了一种使用JavaScript实现冒泡排序动画的方法,通过动态改变竖条的高度和内容来模拟排序过程。作者提到难点在于定时器的设置,由于异步执行特性,需要巧妙处理以实现预期的动画效果。代码示例中展示了如何创建和更新竖条,以及如何处理排序逻辑。尽管目前的实现较为简单,但为后续添加更精细的动画效果留下了改进空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

js实现冒泡排序的动画

这个过程做的特别粗糙,正确的做法应该是为每一个竖条进行定位,在排序的过程中对定位进行更改,并添加动画。我的做法是在排序的过程中将两个竖条的高度和内容进行交换,这样做每次交换的只是高度和内容,且无法添加交换的动画,之后再完善吧!
我觉得最困难的地方在于定时器的设置,因为定时器是异步执行的,无论是把for循环放在定时器里还是将定时器放在for循环中都无法实现想要的效果,最后换了一种思路,先来看代码吧。


<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			/* 这是最外层的样式 */
			.outer {
				width: 80%;
				margin: 20px auto;
				background-color: #00A7DE;
			}

			/* 为按钮添加margin */
			button {
				margin: 5px 10px;
			}

			/* 这是动画的内容区 */
			.space {
				background-color: lightblue;
				/* width: 100%; */
				height: 500px;
				display: flex;
				flex-direction: row;
				justify-content: space-around;
				align-items: flex-end;

			}

			/* 这是竖条 */
			.content {
				background-color: red;
				margin: 0 5px;

				text-align: center;


			}
		</style>
	</head>
	<body>
		<div class="outer">
			<div class="menu">
				<input type="number" name="" id="" value="" placeholder="请输入10到100之间的数" />
				<button type="button">左侧入</button>
				<button type="button">右侧入</button>
				<button type="button">左侧出</button>
				<button type="button">右侧出</button>
				<button type="button">重新排序</button>
				<button type="button">清空</button>
				<button type="button">随机生成</button>


			</div>

			<div class="space">


			</div>
		</div>
		<script src="jquery-3.6.0.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript">
			//排序动画所在的区域
			let space = $('.space')[0];
			// alert(space)、
			let input;



			let btns = $('button');
			console.log(btns);
			//获取区域所在宽度
			let width = $('.space')[0].offsetWidth;
			//获取区域所在高度
			let height = $('.space')[0].offsetHeight;
			//定时器
			let timer;

			console.log(width + ' ' + height);
			console.log(btns)

			//左侧入
			btns.eq(0).click(handle('left', 'insert'));
			//右侧如
			btns.eq(1).click(handle('right', 'insert'));
			//左侧出
			btns.eq(2).click(handle('left', 'delete'));
			//右侧出
			btns.eq(3).click(handle('right', 'delete'));
			//排序按钮
			btns.eq(4).click(function() {
				sort();
			})
			//清空按钮
			btns.eq(5).click(function() {
				$('.space').empty();
			})
			//随机生成
			btns.eq(6).click(function() {
				//alert('ok')
				$('.space').empty();
				clearInterval(timer);
				for (let i = 0; i < 20; i++) {
					let div = document.createElement('div');
					div.className = 'content';

					let item_number = random();
					let item_height = height / 100 * item_number;
					div.innerHTML = item_number;

					div.style.height = item_height + 'px';
					div.style.width = 100 / (20) + '%';
					space.append(div);
				}

			})

			function sort() {
				let heights = [];
				//遍历每个竖条的高度
				$('.content').each(function(index, item) {
					heights.push(item.offsetHeight);


				});
				//这是排序的算法,将i和j放在了定时器的外面,在定时器中对i和j进行加减操作
				let i = 0;
				let j = 0;
				timer = setInterval(function() {
					if (i != heights.length - 1) {
						//将要比较的两个竖条的颜色变成绿色
						$('.content').eq(j).css('backgroundColor', 'lightgreen');
						$('.content').eq(j + 1).css('backgroundColor', 'lightgreen');
						//console.log(heights);
						//前一个比后一个大,对高度和内容进行交换,这里对每一个竖条进行定位更改它的left值进行交换比较好,还可以添加动画效果,刚开始没考虑到动画,后面想改已经有些困难了
						if (j != heights.length - i - 1 && heights[j] > heights[j + 1]) {
							let temp = heights[j + 1];
							let inner = $('.content')[j].innerHTML;
							heights[j + 1] = heights[j];
							heights[j] = temp;
							//这里如果使用的是eq则是jQuery对象,如果是用数组形式取得是DOM对象
							$('.content').eq(j).css('height', heights[j]);
							$('.content').eq(j + 1).css('height', heights[j + 1]);
							$('.content')[j].innerHTML = $('.content')[j + 1].innerHTML;
							$('.content')[j + 1].innerHTML = inner;

						}
						//这里设置延时器的目的是为了将前面要选中进行比较的两个变为绿色的竖条再次恢复为红色,在前面改变颜色的是两个竖条,这里只改变第一个,因为后一个还要和下一个
						//进行比较又要设置为绿色,索性就不改变了。
						//还有一个要注意的点是这里改变的是第(j-1)个元素,但是前面的第一个元素的序号应该是
						//j,按道理这里要恢复颜色的是第j个而不是第(j-1)个,这是因为延时器是异步执行的,定时器的函数执行完之后它才会执行,但是在下面定时器的回调函数
						//会对j进行++的操作,所以当延时器执行的时候第(j-1)个才是之前设置为绿色的第一个。
						setTimeout(function() {
							if (j != 0)
								$('.content').eq(j - 1).css('backgroundColor', 'red');


						}, 100)
						j++;
						//这里已经排好了一个元素,将排好的设置为黄色,开始外层的第二次循环
						if (j == heights.length - i - 1) {
							i++;
							$('.content').eq(j).css('backgroundColor', 'yellow');
							//这里将前一个元素的颜色设置为红色是因为前面只恢复了选中进行比较的两个元素中的第一个,在这里已经没有下一个要比较的元素了,就将它恢复为红色
							$('.content').eq(j - 1).css('backgroundColor', 'red');
							j = 0;
						}
					} else {
						//排序结束将剩下的第一个也变成黄色,并清除定时器
						$('.content').eq(0).css('backgroundColor', 'yellow');
						clearInterval(timer);
					}
				}, 150);






			}
			//对input中的内容进行判断
			function judge(number) {
				if (number == '') {
					alert('请输入数字');
					return false;
				} else if (number < 10 || number > 100) {
					alert('请输入10-100之间的数字');
					return false;
				} else {
					return true;
				}
			}
			//对内容进行左右出入的操作
			function handle(direction, toDo) {


				return function() {
					console.log('success');
					if (toDo == 'insert') {
						let number = $('input').val();
						if (direction == 'right') {


							if (judge(number)) {
								space.append(newDiv(number));
								//每添加一个节点都要重新计算一下宽度,对所有竖条进行更新
								updata();
							} else {
								return;
							}


						} else if (direction == 'left') {

							if (judge(number)) {
								space.prepend(newDiv(number));
								updata();
							} else {
								return;
							}

						} else {
							console.log('参数错误');
						}
					} else if (toDo == 'delete') {
						if (direction == 'right') {
							$('.space div:last').remove();
							//删除节点也要更新所有竖条的宽度
							updata();
						} else if (direction == 'left') {
							$('.space div:first').remove();
							updata();
						}
					}
				}

			}
			//生成一个新的竖条
			function newDiv(number) {
				let div = document.createElement('div');
				div.innerHTML = number;
				div.className = 'content';
				div.style.height = parseInt(height / 100 * number) + 'px';

				let contents = $('.content');
				if (contents.length == 0 || contents.length == 1) {
					div.style.width = '50%'
				} else {
					div.style.width = 100 / (contents.length + 1) + '%';
				}
				return div;

			}
			//更新操作
			function updata() {
				//console.log();
				if ($('.content').length != 0 && $('.content').length != 1)
					$('.content').css('width', width / $('.content').length);
			}
			//随机生成一个10到100之间的数
			function random() {
				return parseInt(Math.random() * 91 + 10);
			}
		</script>
	</body>
</html>

在这里插入图片描述
这是效果图,把时间设置长一点可以观察的更清楚。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值