Canvas制作排序算法演示动画

tips: 形象化演示排序算法可以让初学者快速理解,比较好的例子:jun-lu的SortAnimate旧金山大学的David Galles教授的算法演示课件。最近在看canvas,试着用js+canvas自己做了一个。

实现思路

  • 获取输入字符串
  • 存入数组S[]
  • 新建一个对象数组Rect[]{ x , y , target_x , target_y , text:S[i]}(注:x , y 是当前坐标,target_x , target_y 是目的坐标,text 记录字符)
  • 排序
  • 使用插入排序进行顺序排序,当数值有交换行为时, 用track_insert[]记录进行交换的元素在数组中的位置(方便在绘制动画时进行坐标定位)
  • 因为我用的是插入排序,属于arr[i]arr[i+1]进行交换,所以只需要记录i就可以。
  • 绘制
  • 图片绘制function Draw(){}
  • 图片坐标更新function Update(){}
  • 使用setInterval()定时调用Draw()Update()函数进行页面刷新

效果

初始界面

排序过程

gif演示

小结

做动画都是一个原理,不短刷新更新坐标,擦除,绘制,之前用opencv做的2d的小游戏也是同样的原理。

Source code

.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <link rel="stylesheet" type="text/css" href="css/demo.css"/>
    <script type="text/javascript"src="js/demo2.js"></script>
    <title>Demo</title>
</head>
<body>  
    <div id="container">
        <div>
            <p>Input String:
                <input  name="string" id="tin" type="text"/>
            </p>                    
        </div>
        <div>
            <p> 
                <input type="button" onclick="showDemo()"id="bin" value="Show"/>
            </p>
            <canvas id="mycanvas"  ></canvas>
        </div>
    </div>
</body>
</html>
.js
var S;
var Coordinate_y = 40;
var Rect = new Array();
var track_insert = new Array();
var cons = 0;
var cnt;

function func() {
//获取字符串,存入数组
    S = document.getElementsByName("string")[0].value.split("");
//依据数组元素,完成对象数组
    for (var i = 0; i < S.length; i++) {
        var rect = {
            x: 30 * i,
            y: Coordinate_y,
            target_x: 30 * i,
            target_y: Coordinate_y,
            text: S[i]
        }
        Rect.push(rect);
    }
    insertSort(S);
}

function insertSort(arr) {
    var i = 1,
    j, key, temp;
    for (; i < arr.length; i++) {
        j = i;
        key = arr[i];
        while (--j >= 0) {
            if (arr[j] > key) {
                arr[j + 1] = arr[j];
                arr[j] = key;
//当数据有交换时,记录下标
                track_insert.push(j);
            } else {
                break;
            }
        }
    }
}
//坐标更新
function update() {
    if (cons > track_insert.length) {
        return;
    }
    if (cons == 0) {
        cnt = track_insert[cons];
        Rect[cnt].target_x = Rect[cnt + 1].x;
        Rect[cnt + 1].target_x = Rect[cnt].x;
        cons += 1;
        console.log(cnt);
    }
    if (Rect[cnt].x == Rect[cnt].target_x) {
        if (cons == track_insert.length) {
            cons += 1;
            return;
        }
        var tem = Rect[cnt];
        Rect[cnt] = Rect[cnt + 1];
        Rect[cnt + 1] = tem;
        cnt = track_insert[cons];
        Rect[cnt].target_x = Rect[cnt + 1].x;
        Rect[cnt + 1].target_x = Rect[cnt].x;
        cons += 1;
        console.log(cnt);
    } else {
        Rect[cnt].x += 1;
        Rect[cnt + 1].x -= 1;
    }
}
//绘制图像
function draw(context) {
    context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    for (var i = 0; i < Rect.length; i++) {
        if ((Rect[i].x - Rect[i].target_x) >= 2 || (Rect[i].x - Rect[i].target_x) < -2) {
            context.fillStyle = "yellow";
            context.fillRect(Rect[i].x, Rect[i].y, 25, 25);
            context.fillStyle = "blue";
            context.fillText(Rect[i].text, Rect[i].x + 10, Rect[i].y + 15);
        } else {
            context.strokeStyle = "blue";
            context.strokeRect(Rect[i].x, Rect[i].y, 25, 25);
            context.fillStyle = "blue";
            context.fillText(Rect[i].text, Rect[i].x + 10, Rect[i].y + 15);
        }
    }
    context.fillText("插入排序", 40, 80);
}
function showDemo() {
    func();
    var c = document.getElementById("mycanvas");
    c.width = 600;
    c.height = 300;
    var context = c.getContext("2d");
//40ms调用一次函数
    setInterval(function() {
        draw(context);
        update();
    }, 40);
}
.css
input#tin{
    margin-bottom: 5px;
    background-color: #fff;opacity:0.85;8
    width:20px;
    height:25px; 
    border-width: 1;
    font-size: 17px; 
    color: #000; 
    font-weight: 500; 
    border-radius: 5px;
    cursor:pointer; 
}
input#bin{
    background-color: gray;
    width:80; 
    height:25; 
    border-width: 2; 
    font-size: 20px; 
    color: #FFFFFF; 
    font-weight: 500;
    cursor:pointer; 
    border-radius: 5px;
}
canvas#mycanvas{
    border:1px solid;
    width: 600px;
    height: 300px;
    margin-top: 5px;
    border-radius: 5px;
}
div#container{
    margin-left: 70px;
}

转载于:https://www.cnblogs.com/coderleon/p/4784095.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
构建一个算法演示系统,需要考虑以下几方面的内容: 1. 确定演示内容:首先需要明确需要演示的算法类型,包括排序、搜索、图论等等。然后针对不同类型的算法,需要确定详细的演示内容,如算法流程、关键步骤、关键数据结构等,最终形成一份演示教程。 2. 选择演示工具:根据演示内容的不同,需要选择不同的演示工具。比如,对于排序算法,可以选择使用可视化工具(如Visualgo)来演示过程;对于图论算法,可以使用HTML、CSS、JavaScript等技术,结合Canvas或SVG等绘图工具来实现演示效果。 3. 实现演示效果:根据演示教程和选定的演示工具,需要进行具体的实现。这包括撰写演示代码、绘制演示图形、选择和输入数据等等。 4. 考虑交互体验:对于算法演示系统来说,良好的交互体验是非常重要的。比如,可以添加手工操作功能,使得用户可以自行操作算法演示过程;可以添加一些动态效果,如动画、音效等,使得演示过程更加直观和生动。 5. 确定发布方式:最后需要确定算法演示系统的发布方式。这可以是一个独立的网站、一个单独的应用程序,或者是一个代码库,供其他业务系统或学习者使用。 总之,构建一个好的算法演示系统,需要对演示教程、演示工具、实现效果、交互体验等方面进行全面的考虑和实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值