如何刷新 HTML bag 上的 Canvas?

2024-01-31

我有一个 javascript 程序,可以在屏幕上绘制一百个圆圈,它们可以在画布上自行弹跳。目前,我在它们上面画了一个空矩形以擦除它们的下一代。但是有没有更好的方法来擦除和刷新 HTML 页面上的 Canvas。

Code:

    function  drawScreen () {
    context.fillStyle = '#EEEEEE';
    context.fillRect(0, 0, theCanvas.width, theCanvas.height);
    //Box
    context.strokeStyle = '#000000'; 
    context.strokeRect(1,  1, theCanvas.width-2, theCanvas.height-2);

    update();
    testWalls();
    collide();
    render();
}

如果您想尝试的话,这里是所有代码:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH5EX7: Balls With Simple Interactions</title>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);  
function eventWindowLoaded() {
    canvasApp();
}

function canvasApp() {
    var numBalls = 200 ;
    var maxSize = 15;
    var minSize = 5;
    var maxSpeed = maxSize+5;
    var balls = new Array();
    var tempBall;
    var tempX;
    var tempY;
    var tempSpeed;
    var tempAngle;
    var tempRadius;
    var tempRadians;
    var tempvelocityx;
    var tempvelocityy;

    function  drawScreen () {
        context.fillStyle = '#EEEEEE';
        context.fillRect(0, 0, theCanvas.width, theCanvas.height);
        //Box
        context.strokeStyle = '#000000'; 
        context.strokeRect(1,  1, theCanvas.width-2, theCanvas.height-2);

        update();
        testWalls();
        collide();
        render();
    }

    function update() {
        var ball;
        for (var i =0; i <balls.length; i++) {
            ball = balls[i];
            ball.nextx = (ball.x += ball.velocityx);
            ball.nexty = (ball.y += ball.velocityy);
        }
    }

    function testWalls() {
        var ball;
        var testBall;

        for (var i =0; i <balls.length; i++) {
            ball = balls[i];

            if (ball.nextx+ball.radius > theCanvas.width) {
                ball.velocityx = ball.velocityx*-1;
                ball.nextx = theCanvas.width - ball.radius;

            } else if (ball.nextx-ball.radius < 0 ) {
                ball.velocityx = ball.velocityx*-1;
                ball.nextx =  ball.radius;

            } else if (ball.nexty+ball.radius > theCanvas.height ) {
                ball.velocityy = ball.velocityy*-1;
                ball.nexty = theCanvas.height - ball.radius;

            } else if(ball.nexty-ball.radius < 0) {
                ball.velocityy = ball.velocityy*-1;
                ball.nexty =  ball.radius;
            }
        }
    }

    function render() {
        var ball;
        context.fillStyle = "#000000";
        for (var i =0; i <balls.length; i++) {
            ball = balls[i];
            ball.x = ball.nextx;
            ball.y = ball.nexty;

            context.beginPath();
            context.arc(ball.x,ball.y,ball.radius,0,Math.PI*2,true);
            context.closePath();
            context.fill();
        }
    }

    function collide() {
        var ball;
        var testBall;
        for (var i =0; i <balls.length; i++) {
            ball = balls[i];
            for (var j = i+1; j < balls.length; j++) {
                testBall = balls[j];
                if (hitTestCircle(ball,testBall)) {
                    collideBalls(ball,testBall);
                 }
            }
        }
    }

    function hitTestCircle(ball1,ball2) {
        var retval = false;
        var dx = ball1.nextx - ball2.nextx;
        var dy = ball1.nexty - ball2.nexty;
        var distance = (dx * dx + dy * dy);
        if (distance <= (ball1.radius + ball2.radius) * (ball1.radius + ball2.radius) ) {
              retval = true;
        }
        return retval;
    }

    function collideBalls(ball1,ball2) {
        var dx = ball1.nextx - ball2.nextx;
        var dy = ball1.nexty - ball2.nexty;

        var collisionAngle = Math.atan2(dy, dx);

        var speed1 = Math.sqrt(ball1.velocityx * ball1.velocityx + ball1.velocityy * ball1.velocityy);
        var speed2 = Math.sqrt(ball2.velocityx * ball2.velocityx + ball2.velocityy * ball2.velocityy);

        var direction1 = Math.atan2(ball1.velocityy, ball1.velocityx);
        var direction2 = Math.atan2(ball2.velocityy, ball2.velocityx);

        var velocityx_1 = speed1 * Math.cos(direction1 - collisionAngle);
        var velocityy_1 = speed1 * Math.sin(direction1 - collisionAngle);
        var velocityx_2 = speed2 * Math.cos(direction2 - collisionAngle);
        var velocityy_2 = speed2 * Math.sin(direction2 - collisionAngle);

        var final_velocityx_1 = ((ball1.mass - ball2.mass) * velocityx_1 + (ball2.mass + ball2.mass) * velocityx_2)/(ball1.mass + ball2.mass);
        var final_velocityx_2 = ((ball1.mass + ball1.mass) * velocityx_1 + (ball2.mass - ball1.mass) * velocityx_2)/(ball1.mass + ball2.mass);

        var final_velocityy_1 = velocityy_1;
        var final_velocityy_2 = velocityy_2;

        ball1.velocityx = Math.cos(collisionAngle) * final_velocityx_1 + Math.cos(collisionAngle + Math.PI/2) * final_velocityy_1;
        ball1.velocityy = Math.sin(collisionAngle) * final_velocityx_1 + Math.sin(collisionAngle + Math.PI/2) * final_velocityy_1;
        ball2.velocityx = Math.cos(collisionAngle) * final_velocityx_2 + Math.cos(collisionAngle + Math.PI/2) * final_velocityy_2;
        ball2.velocityy = Math.sin(collisionAngle) * final_velocityx_2 + Math.sin(collisionAngle + Math.PI/2) * final_velocityy_2;

        ball1.nextx = (ball1.nextx += ball1.velocityx);
        ball1.nexty = (ball1.nexty += ball1.velocityy);
        ball2.nextx = (ball2.nextx += ball2.velocityx);
        ball2.nexty = (ball2.nexty += ball2.velocityy);
    }

    theCanvas = document.getElementById('canvasOne');
    context = theCanvas.getContext('2d');

    for (var i = 0; i < numBalls; i++) {
        tempRadius = 5;
        var placeOK = false;
        while (!placeOK) {
            tempX = tempRadius*3 + (Math.floor(Math.random()*theCanvas.width)-tempRadius*3);
            tempY = tempRadius*3 + (Math.floor(Math.random()*theCanvas.height)-tempRadius*3);
            tempSpeed = 4;
            tempAngle =  Math.floor(Math.random()*360);
            tempRadians = tempAngle * Math.PI/ 180;
            tempvelocityx = Math.cos(tempRadians) * tempSpeed;
            tempvelocityy = Math.sin(tempRadians) * tempSpeed;

            tempBall = {x:tempX,y:tempY, nextX: tempX, nextY: tempY, radius:tempRadius, speed:tempSpeed, angle:tempAngle, velocityx:tempvelocityx, velocityy:tempvelocityy, mass:tempRadius};
            placeOK = canStartHere(tempBall);
        }
        balls.push(tempBall);
    }

    function canStartHere(ball) {
        var retval = true;
        for (var i =0; i <balls.length; i++) {
            if (hitTestCircle(ball, balls[i])) {
                retval = false;
            }
        }
        return retval;
    }
   function gameLoop() {
            window.setTimeout(gameLoop, 20);
            drawScreen()    
        }

    gameLoop();


}

</script>

</head>
<body> 
<div style="position: absolute; top: 50px; left: 50px;">

<canvas id="canvasOne" width="500" height="500">
 Your browser does not support the HTML 5 Canvas. 
</canvas>
</div>

</body>
</html>

我已将最新的工作代码放在这里,以防有人将这篇文章作为参考。透明画布的下垂方式不同,效果非常好。

Code:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Moving In Circle</title>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);  
function eventWindowLoaded() {
    canvasApp();

}

 function canvasApp() {
    var radius = 100;
    var circle = {centerX:250, centerY:250, radius:125, angle:0}
    var ball = {x:0, y:0,speed:.1};

    theCanvas = document.getElementById('canvasOne');
    context = theCanvas.getContext('2d');

    function erraseCanvas() {
        context.clearRect(0,0,theCanvas.width,theCanvas.height);
    }

    function drawScreen () {
        erraseCanvas();

        ball.x = circle.centerX + Math.cos(circle.angle) * circle.radius;
        ball.y = circle.centerY + Math.sin(circle.angle) * circle.radius;
        circle.angle += ball.speed;

        context.fillStyle = "#000000";
        context.beginPath();
            context.arc(ball.x,ball.y,15,0,Math.PI*2,true);
        context.closePath();
        context.fill();
    }

    function gameLoop() {
         window.setTimeout(gameLoop, 20);
         drawScreen()   
    }

    gameLoop();
}

</script>

</head>
<body>  
<div style="position: absolute; top: 50px; left: 50px;">

<canvas id="canvasOne" width="500" height="500">
 Your browser does not support the HTML 5 Canvas. 
</canvas>
</div>

</body>
</html>

透明画布context.clearRect ( x , y , w , h );

x:x 坐标,以像素为单位
y:Y 坐标,以像素为单位
w:宽度,以像素为单位
h:高度,以像素为单位

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何刷新 HTML bag 上的 Canvas? 的相关文章

随机推荐

  • GlGenTextures 不断返回 0

    我正在尝试生成这样的纹理 define checkImageWidth 64 define checkImageHeight 64 static GLubyte checkImage checkImageHeight checkImageW
  • 如何模拟 @InjectMocks 类的方法?

    例如我有处理程序 Component public class MyHandler AutoWired private MyDependency myDependency public int someMethod return anoth
  • 回调()或返回回调()

    可能我对 Node 的事件循环了解不够 说我有一个函数foo其中包含一个异步函数async func 我有吗 1 function foo callback stuff here async func function do somethi
  • 负载平衡线程请求百分比

    我有一个工作线程池 我在其中根据百分比向它们发送请求 例如 工作人员 1 必须处理总请求的 60 工作人员 2 必须处理总请求的 31 最后工作人员 3 必须处理 9 我需要从数学上知道如何缩小数字并保持比率 这样我就不必向线程 1 发送
  • 如何在 MFC 中的 CRichEditCtrl 中显示红色波浪线

    我正在致力于在 MFC 应用程序中实现拼写检查器 我想要做的是在拼写错误的单词下显示红线 我找到了一个示例 但它仅适用于简单的编辑框 因为它可以简单地使用编辑控件默认字体进行计算来绘制波浪线 但它不适用于丰富的编辑控件 因为在丰富的编辑控件
  • Vue组件通信

    我有两个 Vue 组件 Vue component A Vue component B 如何从组件B访问组件A 组件之间的通信如何进行 跨组件通信在 Vue js 文档中并没有引起太多关注 也没有很多教程涵盖这个主题 由于组件应该是隔离的
  • 用于生成用户友好的相对时间戳的 PHP 库

    我正在寻找 PHPlibrary生成用户友好的时间表示 例如 当时间戳为 两小时前 时time 2 3600 有几个现有问题及其答案和博客文章 1 https stackoverflow com questions 2690504 php
  • 为什么 build_runner 在 dart/flutter 中序列化 JSON 时不生成文件

    我只是尝试使用 3 个月前存储的相同命令生成文件 我对后端和 devops 不太擅长 但现在它不再生成文件了 它告诉我使用我不记得的删除命令 但即使使用该命令 我的文件仍然不会生成 这就是我的日志的样子 下面您可以找到一个简单类的代码 我的
  • 为什么 swift 中函数有多种返回类型?

    我注意到这个函数有一个独特的返回类型 func chooseStepFunction backward Bool gt Int gt Int func stepForward input Int gt Int return input 1
  • FileSystemWatcher 在网络机器上设置凭据

    有没有办法为 filesystemwatcher 对象设置凭据 该应用程序在不同的用户上运行 该用户无权访问网络计算机上的目录 但我想向 filesystemwatcher 对象提供凭据 以便它可以侦听该目录 可行吗 不需要 只需确保您的应
  • PHP 强制下载损坏的 .xlsx 文件

    我正在开发一个允许教师上传文档和学生下载文档的网站 然而 有一个问题 Microsoft Word docx 文件下载完美 但下载 Excel xlsx 文件时 Excel 会显示 此文件已损坏 无法打开 对话框 任何对此的帮助将不胜感激
  • Windows 手机 8.1 |如何判断本地文件夹中是否存在文件?

    如何确定文件是否存在于本地文件夹中 Windows Storage ApplicationData Current LocalFolder 在 Windows Phone 8 1 上 不幸的是 目前没有直接的方法来检查文件是否存在 您可以尝
  • PyQt5 QWebEngineView不显示网页

    The part where webpage should be rendered gets white for a fraction of second and then gets empty 这是我的代码 基本上是https www p
  • 构建两个独立数据库集成的最佳方法?

    我在工作中遇到了以下问题 我没有经验或知识来回答这些问题 我希望你们中的一些明智的人能够为我指明正确的方向 任何答案将不胜感激 Scenario 实施立面图案 http en wikipedia org wiki Facade patter
  • 捕获 async void 方法抛出的异常

    使用 Microsoft for NET 的异步 CTP 是否可以在调用方法中捕获异步方法抛出的异常 public async void Foo var x await DoSomethingAsync Handle the result
  • 使用 Python 或其他方法从 PDF 中提取指向另一个 PDF 中页面的链接

    我有 5 个 PDF 文件 每个文件都有指向另一个 PDF 文件中不同页面的链接 这些文件都是大型 PDF 的目录 每个大约 1000 页 使得手动提取成为可能 但非常痛苦 到目前为止 我已尝试在 Acrobat Pro 中打开该文件 我可
  • 如何使用 xsl 1.0 查找最小值和最大值?

    文件 1 xml
  • 如何找到货币的 html 代码?

    美元 的html代码是 36 我如何找到其他货币的 html 代码 多谢 这里有一些 测试 Web 浏览器中的 Unicode 支持 货币符号 http www alanwood net unicode currency symbols h
  • Android 在主屏幕上创建快捷方式

    我想做的是 1 我在一个活动中 有 2 个按钮 如果我单击第一个 则会在主屏幕中创建快捷方式 快捷方式打开一个html页面之前已经下载过 所以我希望它使用默认浏览器 但我不想使用互联网 因为我已经有了该页面 2 第二个按钮创建另一个启动活动
  • 如何刷新 HTML bag 上的 Canvas?

    我有一个 javascript 程序 可以在屏幕上绘制一百个圆圈 它们可以在画布上自行弹跳 目前 我在它们上面画了一个空矩形以擦除它们的下一代 但是有没有更好的方法来擦除和刷新 HTML 页面上的 Canvas Code function