(自己看)HTML5 Canvas下雨动画DEMO演示
2021-05-15 22:30
标签:+= art doc htm die pass magic img amp 本次的实例是HTML5 Canvas下雨动画DEMO演示,用到的知识主要是canvas和一个js的库dat.gui,感觉这个库老猛了,有空看一下。 首先是canvas绘画部分代码 下雨的绘制: 雨水溅开水花的绘制: 这里记录几个点,首先说的是绘制用到的dpr,也就是设备像素比(devicePixelRatio),从这里的代码可以看到,canvas最终绘制的宽高和位置都是要乘以dpr,那照着dpr的公式看canvas绘制的是设备像素?这里还有点不清楚,先记着。再有就是绘制溅开的水花的方法,是每一个水花的小点都是一个对象,并且存有初始化好的canvas,然后用主canvas的drawImage方法进行绘制,嗯,记着。 下面是雨水和水花对象: 雨水Rain: 水花Drop: 首先说Rain对象,对象内部没有贴出来,贴出的是几个主要的方法,主要看它的回收机制recycle方法,只要飞出边界的雨水都会回收到rain_pool数组,而rain数组的是正在飞的雨水。再看Drop对象,就是主要看它的canvas设置了,还有就是init方法里面设置水平和垂直方向速度的方式,作者数学肯定很牛X。 下面是一个Ticker对象: 主要是看requestAnimationFrame,这是一个绘制动画的方法,有时间再去看。传入的listener就是下面说的step。 首先是第三段的地方,作者用了一个巧妙的数学方法增加了雨水下落的范围,主要就是根据wind风速的变化来调节范围。亲自试过,如果不添加这段代码,雨水下降的范围只有屏幕中间的一小部分。第四段是设置雨水的x、y,第五段是水花的x、y。 最后是事件: 主要看的是触屏的touch事件,evt的touches对象就是对多点触屏的保存。 继续努力吧! (自己看)HTML5 Canvas下雨动画DEMO演示 标签:+= art doc htm die pass magic img amp 原文地址:http://www.cnblogs.com/ChenYongHao/p/7749978.html1.开篇
1.1本文目标
2.正文
2.1代码
1 ctx.beginPath();
2 var rain_height = Rain.height * dpr;
3 for (var i = rain.length - 1; i >= 0; i--) {
4 var r = rain[i];
5 var real_x = r.x * dpr;
6 var real_y = r.y * dpr;
7 ctx.moveTo(real_x, real_y);
8 ctx.lineTo(real_x - demo.wind * r.z * dpr * 1.5, real_y -
9 rain_height * r.z);
10 }
11 ctx.lineWidth = Rain.width * dpr;
12 ctx.strokeStyle = demo.rain_color;
13 ctx.stroke();
1 for (var i = drops.length - 1; i >= 0; i--) {
2 var d = drops[i];
3 var real_x = d.x * dpr - d.radius;
4 var real_y = d.y * dpr - d.radius;
5 ctx.drawImage(d.canvas, real_x, real_y);
6 }
1 Rain.prototype.init = function() {
2 this.y = Math.random() * -100;
3 this.z = Math.random() * 0.5 + 0.5;
4 this.splashed = false;
5 }
6 Rain.prototype.recycle = function() {
7 demo.rain_pool.push(this);
8 }
9 // recycle rain particle and create a burst of droplets
10 Rain.prototype.splash = function() {
11 if (!this.splashed) {
12 this.splashed = true;
13 var drops = demo.drops;
14 var drop_pool = demo.drop_pool;
15
16 for (var i=0; i) {
17 var drop = drop_pool.pop() || new Drop();
18 drops.push(drop);
19 drop.init(this.x);
20 }
21 }
22 }
1 // Droplet definition
2 function Drop() {
3 this.x = 0;
4 this.y = 0;
5 this.radius = Math.round(Math.random() * 2 + 1) * demo.dpr;
6 this.speed_x = 0;
7 this.speed_y = 0;
8 this.canvas = document.createElement(‘canvas‘);
9 this.ctx = this.canvas.getContext(‘2d‘);
10
11 // render once and cache
12 var diameter = this.radius * 2;
13 this.canvas.width = diameter;
14 this.canvas.height = diameter;
15
16 var grd = this.ctx.createRadialGradient(this.radius, this.radius , 1, this.radius, this.radius, this.radius);
17 grd.addColorStop(0, demo.rain_color);
18 grd.addColorStop(1, demo.rain_color_clear);
19 this.ctx.fillStyle = grd;
20 this.ctx.fillRect(0, 0, diameter, diameter);
21 }
22 Drop.prototype.init = function(x) {
23 this.x = x;
24 this.y = demo.height;
25 var angle = Math.random() * Math.PI - (Math.PI * 0.5);
26 var speed = Math.random() * Drop.max_speed;
27 this.speed_x = Math.sin(angle) * speed;
28 this.speed_y = -Math.cos(angle) * speed;
29 }
30 Drop.prototype.recycle = function() {
31 demo.drop_pool.push(this);
32 }
1 var Ticker = (function(){
2 var PUBLIC_API = {};
3
4 // public
5 // will call function reference repeatedly once registered, passing elapsed time and a lag multiplier as parameters
6 PUBLIC_API.addListener = function addListener(fn) {
7 if (typeof fn !== ‘function‘) throw(‘Ticker.addListener() requires a function reference passed in.‘);
8
9 listeners.push(fn);
10
11 // start frame-loop lazily
12 if (!started) {
13 started = true;
14 queueFrame();
15 }
16 };
17
18 // private
19 var started = false;
20 var last_timestamp = 0;
21 var listeners = [];
22 // queue up a new frame (calls frameHandler)
23 function queueFrame() {
24 if (window.requestAnimationFrame) {
25 requestAnimationFrame(frameHandler);
26 } else {
27 webkitRequestAnimationFrame(frameHandler);
28 }
29 }
30 function frameHandler(timestamp) {
31 var frame_time = timestamp - last_timestamp;
32 last_timestamp = timestamp;
33 // make sure negative time isn‘t reported (first frame can be whacky)
34 if (frame_time ) {
35 frame_time = 17;
36 }
37 // - cap minimum framerate to 15fps[~68ms] (assuming 60fps[~17ms] as ‘normal‘)
38 else if (frame_time > 68) {
39 frame_time = 68;
40 }
41
42 // fire custom listeners
43 for (var i = 0, len = listeners.length; i ) {
44 listeners[i].call(window, frame_time, frame_time / 16.67);
45 }
46
47 // always queue another frame
48 queueFrame();
49 }
50
51 return PUBLIC_API;
52 }());
1 demo.step = function(time, lag) {
2 // localize common references
3 var demo = window.demo;
4 var speed = demo.speed;
5 var width = demo.width;
6 var height = demo.height;
7 var wind = demo.wind;
8 var rain = demo.rain;
9 var rain_pool = demo.rain_pool;
10 var drops = demo.drops;
11 var drop_pool = demo.drop_pool;
12
13 // multiplier for physics
14 var multiplier = speed * lag;
15
16 // spawn drops
17 demo.drop_time += time * speed;
18 while (demo.drop_time > demo.drop_delay) {
19 demo.drop_time -= demo.drop_delay;
20 var new_rain = rain_pool.pop() || new Rain();
21 new_rain.init();
22 var wind_expand = Math.abs(height / new_rain.speed * wind); // expand spawn width as wind increases
23 var spawn_x = Math.random() * (width + wind_expand);
24 if (wind > 0) spawn_x -= wind_expand;
25 new_rain.x = spawn_x;
26 rain.push(new_rain);
27 }
28
29 // rain physics
30 for (var i = rain.length - 1; i >= 0; i--) {
31 var r = rain[i];
32 r.y += r.speed * r.z * multiplier;
33 r.x += r.z * wind * multiplier;
34 // remove rain when out of view
35 if (r.y > height) {
36 // if rain reached bottom of view, show a splash
37 r.splash();
38 }
39 // recycle rain
40 if (r.y > height + Rain.height * r.z || (wind 0 && r.x > width + wind)) {
41 r.recycle();
42 rain.splice(i, 1);
43 }
44 }
45
46 // splash drop physics
47 var drop_max_speed = Drop.max_speed;
48 for (var i = drops.length - 1; i >= 0; i--) {
49 var d = drops[i];
50 d.x += d.speed_x * multiplier;
51 d.y += d.speed_y * multiplier;
52 // apply gravity - magic number 0.3 represents a faked gravity constant
53 d.speed_y += 0.3 * multiplier;
54 // apply wind (but scale back the force)
55 d.speed_x += wind / 25 * multiplier;
56 if (d.speed_x drop_max_speed) {
57 d.speed_x = -drop_max_speed;
58 }else if (d.speed_x > drop_max_speed) {
59 d.speed_x = drop_max_speed;
60 }
61 // recycle
62 if (d.y > height + d.radius) {
63 d.recycle();
64 drops.splice(i, 1);
65 }
66 }
67
68 demo.draw();
69 }
1 // handle interaction
2 demo.mouseHandler = function(evt) {
3 demo.updateCursor(evt.clientX, evt.clientY);
4 }
5 demo.touchHandler = function(evt) {
6 evt.preventDefault();
7 var touch = evt.touches[0];
8 demo.updateCursor(touch.clientX, touch.clientY);
9 }
10 demo.updateCursor = function(x, y) {
11 x /= demo.width;
12 y /= demo.height;
13 var y_inverse = (1 - y);
14
15 demo.drop_delay = y_inverse*y_inverse*y_inverse * 100 + 2;
16 demo.wind = (x - 0.5) * 50;
17 }
18
19 document.addEventListener(‘mousemove‘, demo.mouseHandler);
20 document.addEventListener(‘touchstart‘, demo.touchHandler);
21 document.addEventListener(‘touchmove‘, demo.touchHandler);
总结
上一篇:PHP自动加载机制