javascript - 在排序函数执行期间强制重绘以动画化步骤

标签 javascript sorting

我一直在尝试在 JS 中制作动画冒泡排序,但每次我运行代码时,它都会从随机顺序变为即时排序。每次我交换颜色代码数组中的两个东西后,如何让它重新绘制并停止一段时间。

<html>
<body>
<canvas id="myCanvas"   width="300" height="700" style="border:1px solid #d3d3d3;">
</canvas>
<script>
function swap(nums, pos1,pos2) {
	var a = nums[pos1];
	nums[pos1] = nums[pos2];
	nums[pos2] = a;
}
function shuffle(nums) {
	for (var i = 0; i < 1000; i++) {
		var num1 = Math.floor((Math.random())*26);
		var num2 = Math.floor((Math.random())*26);
		swap(nums,num1,num2);
	}
}
function sleep(seconds) 
{
  var e = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= e) {}
}
function drawIt(nums) {
	var c = document.getElementById("myCanvas");
	var ctx = c.getContext("2d");
	for (var i = 0; i < nums.length; i++) {
		var c = document.getElementById("myCanvas");
		var ctx = c.getContext("2d");	
		ctx.beginPath();
		ctx.rect(10, i * 20 + 10, 50, 20);
		ctx.stroke();
		ctx.fillStyle = "rgba(" + nums[i] + ", " + nums[i] + ", " + nums[i] + ", 1)";
		ctx.fill();
	}
}
var nums = new Array();
for (var i = 0; i<=250; i+=10) {
	nums[i/10] = i;
}
shuffle(nums);
drawIt(nums);
for (var i = 0; i < nums.length-1; i++) {
	for (var j = i+1; j < nums.length; j++) {
		if (nums[i] > nums[j]) {
			swap(nums, i,j);
			drawIt(nums);
		}
	}
} 
</script>
</body>
</html>

我尝试使用 setTimeout() 但没有任何效果。

编辑:

这是您的意思吗,因为这仍然无法正常工作。

<html>
<body>
<canvas id="myCanvas"   width="300" height="800" style="border:1px solid #d3d3d3;">
</canvas>
<script>
function swap(nums, pos1,pos2) {
	var a = nums[pos1];
	nums[pos1] = nums[pos2];
	nums[pos2] = a;
}
function shuffle(nums) {
	for (var i = 0; i < 1000; i++) {
		var num1 = Math.floor((Math.random())*26);
		var num2 = Math.floor((Math.random())*26);
		swap(nums,num1,num2);
	}
}
var counter1 = 0;
var counter2 = 1;
function drawIt(nums) {
	if (nums[counter1] > nums[counter2]) {
		swap(nums, counter1,counter2);
	}
	var c = document.getElementById("myCanvas");
	var ctx = c.getContext("2d");
	for (var i = 0; i < nums.length; i++) {
		var c = document.getElementById("myCanvas");
		var ctx = c.getContext("2d");
		ctx.beginPath();
		ctx.lineWidth = "1";
		ctx.strokeStyle = "rgba(" + nums[i] + ", " + nums[i] + ", " + nums[i] + ", 1)";
		ctx.rect(10, i * 15 + 10, 50, 15);
		ctx.stroke();
		ctx.beginPath();
		ctx.rect(10, i * 15 + 10, 50, 15);
		ctx.stroke();
		ctx.fillStyle = "rgba(" + nums[i] + ", " + nums[i] + ", " + nums[i] + ", 1)";
		ctx.fill();
	}
	if (counter2 < nums.length) {
		counter2++;
	}
	else {
		counter1++;
		counter2 = counter1+1;
	}
}
var nums = new Array();
for (var i = 0; i<=250; i+=5) {
	nums[i/5] = i;
}
shuffle(nums);
drawIt(nums);
for (var i = 0; i < (nums.length*(nums.length-1)) / 2; i++) {
	setTimeout(drawIt(nums), 2000);
}
</script>
</body>
</html>

最佳答案

不幸的是,当您的线程仍在运行时,无法强制绘制或更新 DOM。解决这个问题的方法是使您的排序算法可重入,以便可以从计时器或通过 setTimeout 调用它。每次触发计时器时,您都会执行一次排序迭代,然后绘制结果。

在通过可视化研究算法时,有时这有点烦人,因为如果不修改算法就无法实现逐步可视化。

编辑:添加了实现“可重入”排序的工作代码片段。

<html>
<body>
<canvas id="myCanvas"   width="300" height="700" style="border:1px solid #d3d3d3;">
</canvas>
<script>
function swap(nums, pos1,pos2) {
	var a = nums[pos1];
	nums[pos1] = nums[pos2];
	nums[pos2] = a;
}
function shuffle(nums) {
	for (var i = 0; i < 1000; i++) {
		var num1 = Math.floor((Math.random())*26);
		var num2 = Math.floor((Math.random())*26);
		swap(nums,num1,num2);
	}
}
function sleep(seconds) 
{
  var e = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= e) {}
}
function drawIt(nums) {
	var c = document.getElementById("myCanvas");
	var ctx = c.getContext("2d");
	for (var i = 0; i < nums.length; i++) {
		var c = document.getElementById("myCanvas");
		var ctx = c.getContext("2d");	
		ctx.beginPath();
		ctx.rect(10, i * 20 + 10, 50, 20);
		ctx.stroke();
		ctx.fillStyle = "rgba(" + nums[i] + ", " + nums[i] + ", " + nums[i] + ", 1)";
		ctx.fill();
	}
}
var nums = new Array();
for (var i = 0; i<=250; i+=10) {
	nums[i/10] = i;
}
shuffle(nums);



function sort()
{    
    var i=0;
    var j=0;
    var sortComplete=false;
    var reentrantSort = function()
    {
        if (nums[i] > nums[j]){
            swap(nums, i, j);
            drawIt(nums)
        }
        j++;
        if (j == nums.length){
            j=0;i++;
            if (i == nums.length ) {
                i=0;j=0;
                sortComplete=true; //Sorting is done
            }
        }
        if (!sortComplete){ // If sort still not complete
            setTimeout(reentrantSort,40); // Run next iteration in 40 ms.
        }
    };
    reentrantSort();
}

sort();
</script>
</body>
</html>

关于javascript - 在排序函数执行期间强制重绘以动画化步骤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44252193/

相关文章:

javascript - 拖动时将 Google map 标记位置发送到 Flask

JavaScript 使用 EventListener 和 jQuery 添加和删除 <tr>

javascript - 关于 Javascripts Prototype 的几个问题

javascript - 如何创建material-ui.js文件?

python - 排序算法命名法

MySQL 按不同计数排序

php - 如何根据 2 个键对 PHP 数组进行排序,一个是升序,另一个是降序

javascript - 为什么 Internet Explorer 9 不会对此单击事件使用react? [里面有简短的 jsFiddle 代码]

java - 按属性对自定义对象的 ArrayList 进行排序

sorting - 如何使用默认排序函数对golang中的整数数组进行排序