26.运用物理知识创建动画(1)

本节将创建一个简单的太空场景,其中在太空深处有一个动态的小行星群。

1、准备工作

本节开头的JavaScript代码并没有什么特别之处,实际上,它与上一章使用的代码几乎完全相同。主要的不同之处在于,上一章使用的对象是形状,而本章使用的对象是小行星。

将以下代码添加到一个外部JavaScrit文件中,并用一个可读性强的名称为其命名,如astcroids.js:

$(document).ready(function() { 
        var canvas = $("#myCanvas"); 
        var context = canvas.get(0).getContext("2d"); 
        var canvasWidth = canvas.width(); 
        var canvasHeight = canvas.height(); 
        $(window).resize(resizeCanvas); 
        function resizeCanvas() { 
                canvas.attr("width", $(window).get(0).innerWidth); 
                canvas.attr("height", $(window).get(0).innerHeight); 
                canvasWidth = canvas.width(); 
                canvasHeight = canvas.height(); 
        }; 
        resizeCanvas(); 
        var playAnimation = true; 
        var startButton = $("#startAnimation"); 
        var stopButton = $("#stopAnimation"); 
        startButton.hide(); 
        startButton.click(function() { 
                $(this).hide(); 
                stopButton.show(); 
                playAnimation = true; 
                animate(); 
        }); 
        stopButton.click(function() { 
                $(this).hide(); 
                startButton.show(); 
                playAnimation = false; 
        }); 
        var Asteroid = function(x, y, radius) { 
                this.x = x; 
                this.y = y; 
                this.radius = radius; 
        }; 
        var asteroids = new Array(); 
        for (var i = 0; i < 10; i++) { 
                var x = 20+(Math.random()*(canvasWidth-40)); 
                var y = 20+(Math.random()*(canvasHeight-40)); 
                var radius = 5+Math.random()*10; 
 
                asteroids.push(new Asteroid(x, y, radius)); 
        }; 
 
        function animate() { 
                context.clearRect(0, 0, canvasWidth, canvasHeight); 
                context.fillStyle = "rgb(255, 255, 255)"; 
 
                var asteroidsLength = asteroids.length; 
                for (var i = 0; i < asteroidsLength; i++) { 
                        var tmpAsteroid = asteroids[i]; 
 
                        context.beginPath(); 
                        context.arc(tmpAsteroid.x, tmpAsteroid.y, tmpAsteroid.radius, 0, Math.PI*2, false); 
                        context.closePath(); 
                        context.fill(); 
                }; 
 
                if (playAnimation) { 
                        setTimeout(animate, 33); 
                }; 
        }; 
 
        animate(); 
});

下一步就是构造CSS文件,让画布的尺寸与浏览器窗口同宽。另外,还要使用CSS来移动Start和Stop按钮,因为如果不这样做,当画布占据整个窗口时,这些按钮将位于浏览器之外。

将包含以下代码的外部CSS文件和JavaScript文件放在相同的目录下,并用一个可读性强的名称为其命名,如canvas.css:

* { margin: 0; padding: 0; } 
html, body { height: 100%; width: 100%; } 
canvas { display: block; } 
 
#myCanvas { 
        background: #001022; 
} 
 
#myButtons { 
        bottom: 20px; 
        left: 20px; 
        position: absolute; } 
 
#myButtons button { 
        padding: 5px; 
}

最后,你需要建立一个HTML文件将所有文件整合到一起。这与上一章建立的HTML文件完全相同,不过文件要小得多,因为所有的JavaScript代码都在一个外部文件中。注意这里新加了一个script元素调用JavaScript文件。如果你的文件名不叫asteroids.js,就需要更改调用文件的名称。

将包含以下代码的HTML文件和其他文件放在相同的目录下,并命名为index.html:

 
<!DOCTYPE html> 
 
<html> 
        <head> 
                <title>Implementing advanced animation</title> 
                <meta charset="utf-8"> 
 
                <link href="canvas.css" rel="stylesheet" type="text/css"> 
 
                <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> 
                <script type="text/javascript" src="asteroids.js"></script> 
        </head> 
 
        <body> 
                <canvas id="myCanvas" width="500" height="500"> 
                        <!-- Insert fallback content here --> 
                </canvas> 
                <div id="myButtons"> 
                        <button id="startAnimation">Start</button> 
                        <button id="stopAnimation">Stop</button> 
                </div> 
        </body> 
</html>

如果使用现代浏览器加载该html页面,应该会看到一个蓝色的宽大背景(画布),在其左下角有一个Stop接钮和一群四散分布的小行星(Animating with physics_1.html)。单击Stop按钮可以让背景中的动画停下来。

2、速度

前面的教程介绍过通过增加或减少形状的x和y位置来移动形状,同样的方法也可以赋予每个形状速度。速度包括物体的速率和方向。速率是指像素移动的数目,方向是指向左和向右(x)、向上和向下(y)。

上一章中的速度存在的问题是,它们要么是完全随机的,要么是完全相同的。因此,我们可以将这两种情况中和一下,让每颗小行星采用不同的飞行速度。为此,你需要在Asteroid类中定义两个新属性,代码如下:

 
var Asteroid = function(x, y, radius, vX, vY) { 
        this.x = x; 
        this.y = y; 
        this.radius = radius; 
 
        this.vX = vX; 
        this.vY = vY; 
}; 

适过添加vX和vY属性,现在每颗小行星可以拥有各自不同的速度.注意类函数中参数vX和vY的设置方法,当你创建一颗新的小行星时,可以通过这两个参数来设置速度。那么,接下来需要为每颗小行星设置不同的速度,速度定义了每个动画循环中小行星移动的像素数目。

为了在循环中创建所有的小行星,需要在radius变量下面添加以下代码:

var vX = Math.random()*4-2; 
var vY = Math.random()*4-2; 

另外,还需要使用以下代码替换radius变量下一行的代码,以便把新的速度作为参数传递给Asteroid类:

asteroids.push(new Asteroid(x, y, radius, vX, vY)); 

在本示例中,在x轴和y轴上同时将速度设置为一个介于-2到2之间的随机数。Math.random方法将会产生一个介于0到1之间的小数。因此,为了得到一个介于-2到2之间的数,需要分两步完成。第一步,将随机数乘以4,得到一个介于0到4之间的随机数。第二步非常简单,只需将该随机数减去2,这样将得到一个介于-2(0减2)到2(4减2)之间的数。你可以使用该方法计算介于任意范围内的随机数。

仅对代码进行这些修改,还不能改变小行星的速度。你还需要使用新的速度属性来更新每颗小行星的x和y位置。在动画循环中的tmpAsteroid变量声明下面添加以下代码:

tmpAsteroid.x += tmpAsteroid.vX; 
tmpAsteroid.y += tmpAsteroid.vY;

小行星的当前位置增加了一个确定的像素数。现在每颗小行星各自有了不同的速度,这说明它们将会以不同的速率(每个循环的像素数)和方向运动。有些动画看上去非常自然和流畅,其秘诀就在于实现了这种不同速度的运动。

刷新或加载该HTML文件,你应该会看到一群类似于小行星的物体在画布上运动(Animating with physics_2.html)。继续刷新页面,可以看到这些小行星将从不同的位置出发,并以不同的速度运动。目前画布中还没有边界,当小行星运动到屏幕的边界快要消失时,你可以单击Stop按钮来留住它们。

文件下载(已下载 2265 次)

发布时间:2013/3/20 下午2:34:18  阅读次数:7580

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号