本篇博文通过制作一个小球运动动画的实例,来学习在HTML5的画布上实现动画制作的方法,同时理解面向对象程序设计的基本思想。

1.绘制小球

先在HTML页面中设置一个画布。

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

再将小球画在canvas(画布)上面。

可编写如下的HTML代码。

<!DOCTYPE html>

<head>

<title>运动的小球(一)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

var x=100, y=100,radius=25;

context.beginPath();

context.arc(x, y, radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle = "blue";

context.fill();

</script>

</body>

</html>

其中,变量x、y、radius分别是小球的圆心坐标(x,y)和半径radius。

将上述HTML代码保存到一个html文本文件中,再在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色的小球。这个小球没有什么特别的,实际上是一个简单的圆形,用arc()函数绘制出来的。

2.让小球动起来

添加一个animation函数,在函数中先用clearRect 清理掉画布里之前的小球圆形,然后重新绘制小球,之后修改小球的圆心坐标。再用window.requestAnimationFrame()控制动画。

设小球x坐标轴(水平方向)的移动速度为xspeed、y坐标轴(竖直方向)的移动速度为yspeed,则修改小球圆心坐标的方法为:x += xspeed;  y +=yspeed; 。

重新编写的HTML代码如下。

<!DOCTYPE html>

<head>

<title>运动的小球(二)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

var x=100, y=100, xspeed=5, yspeed=1, radius=25;

function animation()

{

context.clearRect(0,0,canvas.width,canvas.height);

context.beginPath();

context.arc(x, y, radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle = "blue";

context.fill();

x += xspeed;

y += yspeed;

window.requestAnimationFrame(animation);

}

window.requestAnimationFrame(animation);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色的小球在运动。

3.边界碰撞处理

在浏览器中打开添加了animation函数的html文件,会发现小球很快会移出画布。这是由于animation函数中没有进行边界碰撞测试,因此,需要在修改小球圆心坐标后,判断小球按新的圆心坐标绘制时是否会超出画布的尺寸,并控制相应的速度量反转(增量变减量或者减量变增量)。修改后的animation函数如下:

function animation()

{

context.clearRect(0,0,canvas.width,canvas.height);

context.beginPath();

context.arc(x, y, radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle = "blue";

context.fill();

x += xspeed;

y += yspeed;

if (y+radius>=canvas.height || y-radius<=0)

yspeed = -yspeed;

if (x+ radius >= canvas.width || x-radius<= 0)

xspeed = -xspeed;

window.requestAnimationFrame(animation);

}

修改animation函数后,完整的HTML文件内容如下:

<!DOCTYPE html>

<head>

<title>运动的小球(三)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

var x=100, y=100, xspeed=5, yspeed=1, radius=25;

function animation()

{

context.clearRect(0,0,canvas.width,canvas.height);

context.beginPath();

context.arc(x, y, radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle = "blue";

context.fill();

x += xspeed;

y += yspeed;

if (y+radius>=canvas.height || y-radius<=0)

yspeed = -yspeed;

if (x+ radius >= canvas.width || x-radius<= 0)

xspeed = -xspeed;

window.requestAnimationFrame(animation);

}

window.requestAnimationFrame(animation);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色的小球在运动,并且小球在碰撞到边界后,会改变方向,这样小球继续在框中运动,不会出界。

4.再添加一个运动的小球

分别用   var x1=100, y1=100, xspeed1=5, yspeed1=1, radius1=25;

var x2=50, y2=50, xspeed2=3, yspeed2=1, radius2=15;来表示两个小球的数据。

然后将animation函数中有关小球的绘制和坐标修改语句复制一次并修改相应的变量名即可。

修改后的HTML代码如下。

<!DOCTYPE html>

<head>

<title>运动的小球(四)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

var x1=100, y1=100, xspeed1=5, yspeed1=1, radius1=25;

var x2=50, y2=50, xspeed2=3, yspeed2=1, radius2=15;

function animation()

{

context.clearRect(0,0,canvas.width,canvas.height);

context.beginPath();

context.arc(x1, y1, radius1, 0, Math.PI*2, true);

context.closePath();

context.fillStyle = "blue";

context.fill();

context.beginPath();

context.arc(x2, y2, radius2, 0, Math.PI*2, true);

context.closePath();

context.fillStyle = "red";

context.fill();

x1 += xspeed1;

y1 += yspeed1;

if (y1+radius1>=canvas.height || y1-radius1<=0)

yspeed1 = -yspeed1;

if (x1+ radius1 >= canvas.width || x1-radius1<= 0)

xspeed1 = -xspeed1;

x2 += xspeed2;

y2 += yspeed2;

if (y2+radius2>=canvas.height || y2-radius2<=0)

yspeed2 = -yspeed2;

if (x2+ radius2 >= canvas.width || x2-radius2<= 0)

xspeed2 = -xspeed2;

window.requestAnimationFrame(animation);

}

window.requestAnimationFrame(animation);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色和一个红色的小球在运动。

5.定义小球对象。

按上面的方法,如果再增加一个或多个小球,相应的代码会复制多次。实际上,小球是一个对象,它包括圆心坐标(x,y)、半径radius、水平方向的移动速度xspeed、竖直方向的移动速度yspeed和小球颜色等属性,以及绘制小球和小球移动一步(指圆心坐标变化)等操作。显然,将小球可以定义为一个对象更合适。

采用构造函数的方法定义小球对象的HTML代码如下。

<!DOCTYPE html>

<head>

<title>运动的小球(五)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;"></canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

// 定义小球对象

function Ball(x,y,xspeed,yspeed,radius,color){

this.x=x;

this.y=y;

this.xspeed=xspeed;

this.yspeed=yspeed;

this.radius=radius;

this.color=color;

this.draw=function()

{

context.beginPath();

context.arc(this.x,this.y,this.radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle =this.color;

context.fill();

}

this.step=function()

{

this.x += this.xspeed;

this.y += this.yspeed;

if (this.y+this.radius>=canvas.height || this.y-this.radius<=0)

this.yspeed = -this.yspeed;

if (this.x+ this.radius >= canvas.width || this.x-this.radius<= 0)

this.xspeed = -this.xspeed;

}

}

// 创建三个小球

var ball1=new Ball(100,100,5,3,25,"#0000FF");

var ball2=new Ball(50, 40,3,1,20,"#FF0000");

var ball3=new Ball(30, 30, 3, 2, 15,"#00FFFF");

function animation()

{

context.clearRect(0,0,canvas.width,canvas.height);

ball1.draw();

ball2.draw();

ball3.draw();

ball1.step();

ball2.step();

ball3.step();

window.requestAnimationFrame(animation);

}

window.requestAnimationFrame(animation);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色、一个红色和一个青色的三个小球在运动。

采用对象后,增加一个运动小球就很方便了,只需先创建一个小球对象

var ball4=new Ball(10, 20, 3, 2, 15,"#FFFF00");

再添加两条语句  ball4.draw();和 ball4.step();即可。

6.给小球一个长尾效果。

如果将animation函数中的语句 context.clearRect(0,0,canvas.width,canvas.height);改写为如下两条语句:

context.fillStyle = 'rgba(255,255,255,0.3)';

context.fillRect(0,0,canvas.width,canvas.height);

这样在清除前一帧动画时,由于是用一个半透明的fillRect函数填充画布,可以为每个小球增加一个长尾效果。

添加了长尾效果的小球运动动画HTML文档内容如下:

<!DOCTYPE html>

<head>

<title>运动的小球(六)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;"></canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

// 定义小球对象

function Ball(x,y,xspeed,yspeed,radius,color){

this.x=x;

this.y=y;

this.xspeed=xspeed;

this.yspeed=yspeed;

this.radius=radius;

this.color=color;

this.draw=function()

{

context.beginPath();

context.arc(this.x,this.y,this.radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle =this.color;

context.fill();

}

this.step=function()

{

this.x += this.xspeed;

this.y += this.yspeed;

if (this.y+this.radius>=canvas.height || this.y-this.radius<=0)

this.yspeed = -this.yspeed;

if (this.x+ this.radius >= canvas.width || this.x-this.radius<= 0)

this.xspeed = -this.xspeed;

}

}

// 创建三个小球

var ball1=new Ball(100,100,5,3,25,"#0000FF");

var ball2=new Ball(50, 40,3,1,20,"#FF0000");

var ball3=new Ball(30, 30, 3, 2, 15,"#00FFFF");

function animation()

{

context.fillStyle = 'rgba(255,255,255,0.3)';

context.fillRect(0,0,canvas.width,canvas.height);

ball1.draw();

ball2.draw();

ball3.draw();

ball1.step();

ball2.step();

ball3.step();

window.requestAnimationFrame(animation);

}

window.requestAnimationFrame(animation);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色、一个红色和一个青色的三个小球在运动,并且每个小球运动时带有长尾效果,如图1所示。

图1 带有长尾效果的运动小球

7.为画布中的动画添加开始和结束控制。

为了对小球运动的开始和结束进行控制,可以在页面中增加“开始”和“停止”两个按钮,单击相应的按钮产生相应的操作。

添加按钮操作后的HTML代码如下。

<!DOCTYPE html>

<head>

<title>运动的小球(七)</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

<br/><input id="start" type="button" value="开始">

<input id="stop" type="button" value="停止">

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

var handle=0;

// 定义小球对象

function Ball(x,y,xspeed,yspeed,radius,color){

this.x=x;

this.y=y;

this.xspeed=xspeed;

this.yspeed=yspeed;

this.radius=radius;

this.color=color;

this.draw=function()

{

context.beginPath();

context.arc(this.x,this.y,this.radius, 0, Math.PI*2, true);

context.closePath();

context.fillStyle =this.color;

context.fill();

}

this.step=function()

{

this.x += this.xspeed;

this.y += this.yspeed;

if (this.y+this.radius>=canvas.height || this.y-this.radius<=0)

this.yspeed = -this.yspeed;

if (this.x+ this.radius >= canvas.width || this.x-this.radius<= 0)

this.xspeed = -this.xspeed;

}

}

// 创建三个小球

var ball1=new Ball(100,100,5,3,25,"#0000FF");

var ball2=new Ball(50, 50,3,1,20,"#FF0000");

var ball3=new Ball(20, 20, 3, 2, 15,"#00FFFF");

ball1.draw();

ball2.draw();

ball3.draw();

function animation()

{

context.fillStyle = 'rgba(255,255,255,0.3)';

context.fillRect(0,0,canvas.width,canvas.height);

ball1.draw();

ball2.draw();

ball3.draw();

ball1.step();

ball2.step();

ball3.step();

handle=window.requestAnimationFrame(animation);

}

var running=false;

var startBtn=document.getElementById('start');

var stopBtn=document.getElementById('stop');

startBtn.addEventListener('click', function () {

if (!running)

{

handle=requestAnimationFrame(animation);

running=true;

}

});

stopBtn.addEventListener('click', function () {

cancelAnimationFrame(handle);

handle=null;

running=false;

});

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中出现一个蓝色、一个红色和一个青色的三个小球,这三个小球初始时静止。单击“开始”按钮后,小球开始运动,单击“停止”按钮,小球停止运动,在当前位置静止不动。再单击“开始”按钮,小球又开始运动。

JavaScript实例:运动的小球的更多相关文章

  1. 自定义View,随着手指运动的小球

    这个实例是自定的view的初步介绍,要设计的是一个随着手指运动的小球.原理是随时获取手指的坐标,然后在这个坐标上面实时改变自定义view的坐标.这个view仅仅是画了一个圆形而已. 自定义的view ...

  2. JavaScript实例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  3. 每天一个JavaScript实例-从一个div元素删除一个段落

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  4. 每天一个JavaScript实例-推断图片是否载入完毕

    <!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  5. 每天一个JavaScript实例-动态省份选择城市

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 每天一个JavaScript实例-递归实现反转数组字符串

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  7. 每天一个JavaScript实例-html5拖拽

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  8. 每天一个JavaScript实例-canvas绘图

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  9. 一些有用的javascript实例分析(三)

    原文:一些有用的javascript实例分析(三) 10 输入两个数字,比较大小 window.onload = function () { var aInput = document.getElem ...

随机推荐

  1. flex布局实现瀑布流排版

    网上有很多有关js(jq)实现瀑布流和有关瀑布流的插件很多,例如:插件(Masonry,Wookmark等等).按照正常的逻辑思维,瀑布流的排版(item列表)一般都是 由左到右,上而下排序的结果,单 ...

  2. 《Dotnet9》系列-开源C# WPF控件库3《HandyControl》强力推荐

    大家好,我是Dotnet9小编,一个从事dotnet开发8年+的程序员.我最近开始写dotnet分享文章,希望能让更多人看到dotnet的发展,了解更多dotnet技术,帮助dotnet程序员应用do ...

  3. 使用Python为中秋节绘制一块美味的月饼【华为云技术分享】

    每逢佳节… 对于在外的游子,每逢佳节倍思亲.而对于996ICU的苦逼程序猿们,最期待的莫过于各种节假日能把自己丢在床上好好休息一下了.这几天各公司都陆续开始发中秋礼品了.朋友圈各种秀高颜值的月饼,所以 ...

  4. LeetCode刷题--无重复字符的最长子串(中等)

    题目描述: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 " ...

  5. Win7 系统所有应用颜色调整

    不知道按到哪个快捷键了,发现windows7系统桌面,浏览器,PDF阅读器和Eclipse的北京和菜单都编程淡黄色,下面是解决的过程. 方法一:在win7桌面右击 -> 个性化 -> 窗口 ...

  6. 17-Python执行JS代码--PyExecJS、PyV8、Js2Py

    一.Python执行JS代码--PyExecJS.PyV8.Js2Py 1.1.PyExecJS PyExecJS的优点是您不需要照顾JavaScript环境.特别是,它可以在Windows环境中运行 ...

  7. Java修炼——基于TCP协议的Socket编程_双向通信_实现模拟用户登录

    首先我们需要客户端和服务器端. 服务器端需要:1.创建ServerSocket对象.2.监听客户端的请求数据.3.获取输入流(对象流)即用户在客户端所发过来的信息.                  ...

  8. 2018 ACM/ICPC 南京 I题 Magic Potion

    题解:最大流板题:增加两个源点,一个汇点.第一个源点到第二个源点连边,权为K,然后第一个源点再连其他点(英雄点)边权各为1,然后英雄和怪物之间按照所给连边(边权为1). 每个怪物连终点,边权为1: 参 ...

  9. ARTS-S golang单元测试

    golang单元测试 在$GOPATH的src目录下建目录demo_unittest 在目录demo_unittest下建文件calc.go,内容如下: package demo_unittest f ...

  10. Dubbo加权轮询负载均衡的源码和Bug,了解一下?

    本文是对于Dubbo负载均衡策略之一的加权随机算法的详细分析.从2.6.4版本聊起,该版本在某些情况下存在着比较严重的性能问题.由问题入手,层层深入,了解该算法在Dubbo中的演变过程,读懂它的前世今 ...