最近准备学习一些HTML5方面的知识。之前演示小球和天平的页面用的完全是老式的html+jquery,原本想做些动画效果的,结果只能退而求其次,用颜色代替了。
接下来拟定了几个小演示程序,准备用HTML5来做,此前先针对性地做一些非系统性的学习,只要能实现预定目标即可。
本次目标:在canvas画布上绘制彩色小球并实现模拟烟花般的动画效果。
程序很简单,只需要理解canvas元素,在指定位置用指定颜色绘制圆球然后逐帧形成动画就可以了。
考虑到性能因素,在球离开视觉区域或颜色完全变淡后就移除对象,并在每帧补上一定数量的球,这样也能够保证视觉效果。
演示效果如下(浏览器需支持HTML5):
源码如下(由于结构并不复杂,代码中的注释应该能解决大部分疑惑,代码后面附有简单解析。感兴趣的话不妨复制下来自行调试):
5 | <script type="text/javascript" src="../js/jquery-1.9.0.min.js"> </script> |
6 | <script type="text/javascript" src="../js/requestAnimationFrame.js"> </script> |
7 | <script type="text/javascript"> |
14 | var colorweaken = 0.008 |
22 | var balls = new Array() |
25 | var lastframecount = 0 |
34 | canvas = document.getElementById( "image" ) |
36 | if (!canvas.getContext) self.location = "/nohtml5.html" |
38 | var container = $( "#container" ) |
39 | container.width($(window).width()) |
40 | container.height($(window).height()) |
41 | canvas.width = container.width() |
42 | canvas.height = container.height() |
43 | context = canvas.getContext( "2d" ) |
44 | context.font = "16px Arial" |
46 | framestarttime = new Date() |
53 | function animeframe() { |
55 | context.fillStyle = "rgba(0,0,0," + tail + ")" |
56 | context.fillRect(0, 0, canvas.width, canvas.height) |
57 | var newballs = new Array() |
58 | for ( var i in balls) { |
60 | ball.speedy += gravity |
63 | ball.alpha -= colorweaken |
64 | if (ball.x > 0 && ball.x < canvas.width && ball.y > 0 && ball.y < canvas.height && ball.alpha > 0) { |
71 | if (newballs.length < maxballcount ) { |
72 | for ( var i = 0 ; i < Math.min(newballcount, maxballcount - newballs.length); i++) { |
73 | newballs.push(generaterandomball()) |
82 | var thisframetime = new Date() |
83 | if (thisframetime - framestarttime >= 1000) { |
84 | lastframecount = framecount |
86 | framestarttime = thisframetime |
89 | context.fillStyle = "#000" |
90 | context.fillRect(0, 0, 80, 40) |
91 | context.fillStyle = "#FF0" |
92 | context.fillText( "FPS:" + lastframecount, 10, 20) |
94 | requestAnimationFrame(animeframe) |
98 | function drawball(ball) { |
101 | context.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, true ) |
103 | context.fillStyle = "rgba(" + ball.color + "," + ball.alpha + ")" |
108 | function generaterandomball() { |
109 | var ball = new Object() |
111 | ball.x = Math.round(Math.random() * canvas.width / 10) + (canvas.width / 2 - canvas.width / 20) |
112 | ball.y = Math.round(Math.random() * canvas.height / 10) + (canvas.height / 2 - canvas.height / 20) |
114 | ball.color = randomcolor() |
117 | ball.speedx = Math.round(Math.random() * startspeedx * 2) - startspeedx |
118 | ball.speedy = -Math.round(Math.random() * startspeedy) |
123 | function randomcolor() { |
124 | var yellow = Math.round(Math.random() * 255) |
125 | return "255," + yellow + ",0" |
128 | < style type = "text/css" > |
139 | background-color: #000; |
代码解析:
- 在设置各项基本参数的值之后,执行init()方法初始化页面;
- 初始化画布尺寸和基本对象,然后执行animeframe()开始动画;
- 每个animeframe()显示一帧动画,结束后递归自己显示下一帧;
- 每帧要通过各小球的位置和速度计算运动轨迹,并计算重力加速度对纵向速度的影响;
- 小球出界则从数组中移除。这里使用的是相反的方法:只有检测到在界内的才添加到新数组,循环完成后将新旧数组交换;
- 运动中的小球颜色逐渐变淡(增加alpha透明度);
- 使用drawball()方法绘制小球;
- 如果小球数量太少则补球;
- 生成随机球的方法是generaterandomball(),颜色在全红(255,0,0)到全黄(255,255,0)间随机选择。只需要第二个值取随机即可;
- 每秒统计帧数并显示在左上角。
补注:旧版代码使用的是setTimeout实现动画。加入一段兼容性脚本后,改用requestAnimationFrame代替setTimeout来达到更好的性能,并在左上角加入帧数显示(用于测试不同浏览器和设备上的性能)
脚本如下(已保存到单独的requestAnimationFrame.js文件中):
4 | var vendors = [ 'webkit' , 'moz' ]; |
5 | for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { |
6 | window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame' ]; |
7 | window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame' ] || |
8 | window[vendors[x] + 'CancelRequestAnimationFrame' ]; |
11 | if (!window.requestAnimationFrame) { |
12 | window.requestAnimationFrame = function (callback, element) { |
13 | var currTime = new Date().getTime(); |
14 | var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)); |
15 | var id = window.setTimeout( function () { |
16 | callback(currTime + timeToCall); |
18 | lastTime = currTime + timeToCall; |
22 | if (!window.cancelAnimationFrame) { |
23 | window.cancelAnimationFrame = function (id) { |
这只是一个很简单的演示程序,预计在下一个示例作品中实现:
- 提取动画方法,不与程序逻辑混杂在一起;
- 与用户操作互动;
- 简单的碰撞检测。
谢谢你!
楼主你好,我对JS编程也很感兴趣,但是一直找不到好用的IDE,想请问下你是用什么软件编码和调试JS(或者HTML5)呢?感谢!
我用的是WebStorm