最初的想法是仿写win7的泡泡屏保效果,但是对于小球的斜碰问题一直没搞明白(如果你会这个,欢迎留言或者做个demo),所以只是简单处理了碰撞后的速度,有时候会看起来很搞笑~~~funny guy
话不多说,先上demo
https://win7killer.github.io/demo_set/html_demo/canvas/can_ps/ball.html
效果如下:
code:
1 <!DOCTYPE html> 2 <html lang="zh"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>Document</title> 9 <style> 10 * { 11 margin: 0; 12 padding: 0; 13 } 14 15 html { 16 height: 100%; 17 } 18 19 body { 20 width: 100%; 21 height: 100%; 22 background: #333; 23 background: url(./img/6.jpg) no-repeat 0 0; 24 background-size: cover; 25 } 26 27 canvas { 28 display: block; 29 } 30 </style> 31 </head> 32 33 <body> 34 <canvas id="can" width=0 height=0></canvas> 35 <script> 36 var ballsNum = 20; 37 window.onload = function() { 38 39 var can = document.getElementById('can'); 40 can.width = document.body.offsetWidth; 41 can.height = document.body.offsetHeight; 42 var ctx = can.getContext('2d'); 43 var ballR = Math.floor(can.height / 15); 44 ctx.shadowColor = 'rgba(0,0,0,.3)'; 45 ctx.shadowOffsetX = ballR / 5; 46 ctx.shadowOffsetY = ballR / 5; 47 // ctx.shadowBlur = ballR / 10 > 5 ? ballR / 10 : 5; 48 ctx.shadowBlur = 16; 49 50 var aObj = randomBall(ballsNum); 51 var raf = window.requestAnimationFrame(loop); 52 53 function loop() { 54 ctx.clearRect(0, 0, can.width, can.height); 55 for (var i = 0, l = aObj.length; i < l; i++) { 56 fnChange(aObj[i]); 57 checkPeng(aObj, i); 58 } 59 if (raf) { 60 raf = window.requestAnimationFrame(loop); 61 } 62 } 63 64 // 改变圆心坐标 65 function fnChange(obj) { 66 drawArc(obj); 67 obj.x += obj.sx * 10 / 4; 68 obj.y += obj.sy * 5 / 4; 69 70 if (obj.x >= can.width - ballR) { 71 obj.x = can.width - ballR; 72 obj.sx = -1 * obj.sx; 73 } else if (obj.x <= ballR) { 74 obj.x = ballR; 75 obj.sx = -1 * obj.sx; 76 } 77 if (obj.y >= can.height - ballR) { 78 obj.y = can.height - ballR; 79 obj.sy = -1 * obj.sy; 80 } else if (obj.y <= ballR) { 81 obj.y = ballR; 82 obj.sy = -1 * obj.sy; 83 } 84 } 85 //画圆 86 function drawArc(obj) { 87 ctx.save(); 88 ctx.beginPath(); 89 ctx.arc(obj.x % can.width, obj.y % can.height, ballR, 0, 2 * Math.PI); 90 ctx.closePath(); 91 92 var grd = ctx.createRadialGradient(obj.x - ballR * 3 / 10, obj.y - ballR * 4 / 10, ballR / 8, obj.x - ballR * 4 / 10, obj.y - ballR * 4 / 10, ballR * 16 / 10); 93 grd.addColorStop(0, "rgba(255,255,255,1)"); 94 grd.addColorStop(1, obj.scolor); 95 ctx.fillStyle = grd; 96 ctx.fill(); 97 ctx.restore(); 98 } 99 100 function randomBall(num) { 101 var barr = []; 102 var ball; 103 for (var i = 0; i < num || 0; i++) { 104 ball = {}; 105 ball.x = Math.random() * (can.width - ballR * 2) + ballR; 106 ball.y = Math.random() * (can.height - ballR * 2) + ballR; 107 ball.sx = Math.random() * 6 - 6 / 2; 108 ball.sy = Math.random() * 6 - 6 / 2; 109 var scr = Math.round(Math.random() * 200 + 50); 110 var scg; 111 var scb; 112 if (scr > 200) { 113 if (Math.random() > 1) { 114 scg = Math.round(Math.random() * 150 + 50); 115 scb = Math.round(Math.random() * 200 + 50); 116 } else { 117 scb = Math.round(Math.random() * 150 + 50); 118 scg = Math.round(Math.random() * 200 + 50); 119 } 120 } else { 121 scg = Math.round(Math.random() * 200 + 50); 122 scb = Math.round(Math.random() * 200 + 50); 123 } 124 ball.scolor = 'rgba(' + [scr, scg, scb, 1].join(',') + ')'; 125 barr.push(ball); 126 } 127 return barr; 128 } 129 130 //碰撞检测 131 function checkPeng(arr, i) { 132 var j, len; 133 134 for (j = 0, len = arr.length; j < len; j++) { 135 if (i === j) { 136 continue; 137 } 138 var ca = { 139 x: arr[i].x - arr[j].x, 140 y: arr[i].y - arr[j].y 141 } 142 var z = Math.sqrt(Math.pow(ca.x, 2) + Math.pow(ca.y, 2)); 143 var cha = z - ballR * 2; 144 if (cha <= 0) { 145 if (arr[i].x < arr[j].x) { 146 arr[i].x += cha; 147 } else { 148 arr[i].x += -cha; 149 } 150 if (arr[i].y < arr[j].y) { 151 arr[i].y += cha; 152 } else { 153 arr[i].y += -cha; 154 } 155 //arr[i].sy = -1*arr[i].sy; 156 var iTY = arr[i].sy; 157 arr[i].sy = 1 * arr[j].sy; 158 arr[j].sy = iTY; 159 //arr[i].sx = -1*arr[i].sx; 160 var iTX = arr[i].sx; 161 arr[i].sx = 1 * arr[j].sx; 162 arr[j].sx = iTX; 163 } 164 } 165 } 166 } 167 </script> 168 </body> 169 170 </html>
然后是加强版的透明泡泡
https://win7killer.github.io/demo_set/html_demo/canvas/can_ps/ball_1.html
效果如下:
code:
1 <!DOCTYPE html> 2 <html lang="zh"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>Document</title> 9 <style> 10 * { 11 margin: 0; 12 padding: 0; 13 } 14 15 html { 16 height: 100%; 17 } 18 19 body { 20 width: 100%; 21 height: 100%; 22 background: #333; 23 background: url(./img/6.jpg) no-repeat 0 0; 24 background-size: cover; 25 } 26 27 canvas { 28 display: block; 29 } 30 </style> 31 </head> 32 33 <body> 34 <canvas id="can" width=0 height=0></canvas> 35 <script> 36 var ballsNum = 20; 37 window.onload = function() { 38 39 var can = document.getElementById('can'); 40 can.width = document.body.offsetWidth; 41 can.height = document.body.offsetHeight; 42 var ctx = can.getContext('2d'); 43 var ballR = Math.floor(can.height / 15); 44 ctx.shadowColor = 'rgba(0,0,0,.3)'; 45 ctx.shadowOffsetX = ballR / 5; 46 ctx.shadowOffsetY = ballR / 5; 47 // ctx.shadowBlur = ballR / 10 > 5 ? ballR / 10 : 5; 48 ctx.shadowBlur = 16; 49 50 var aObj = randomBall(ballsNum); 51 var raf = window.requestAnimationFrame(loop); 52 function loop() { 53 ctx.clearRect(0, 0, can.width, can.height); 54 for (var i = 0, l = aObj.length; i < l; i++) { 55 fnChange(aObj[i]); 56 checkPeng(aObj, i); 57 } 58 if (raf) { 59 raf = window.requestAnimationFrame(loop); 60 } 61 } 62 63 // 改变圆心坐标 64 function fnChange(obj) { 65 drawArc(obj); 66 obj.x += obj.sx * 10 / 4; 67 obj.y += obj.sy * 5 / 4; 68 69 if (obj.x >= can.width - ballR) { 70 obj.x = can.width - ballR; 71 obj.sx = -1 * obj.sx; 72 } else if (obj.x <= ballR) { 73 obj.x = ballR; 74 obj.sx = -1 * obj.sx; 75 } 76 if (obj.y >= can.height - ballR) { 77 obj.y = can.height - ballR; 78 obj.sy = -1 * obj.sy; 79 } else if (obj.y <= ballR) { 80 obj.y = ballR; 81 obj.sy = -1 * obj.sy; 82 } 83 } 84 //画圆 85 function drawArc(obj) { 86 ctx.save(); 87 ctx.beginPath(); 88 ctx.arc(obj.x % can.width, obj.y % can.height, ballR, 0, 2 * Math.PI); 89 ctx.closePath(); 90 91 var grd1 = ctx.createRadialGradient( 92 obj.x, 93 obj.y, 94 ballR / 2, 95 obj.x, 96 obj.y, 97 ballR * 13 / 10 98 ); 99 // grd1.addColorStop(0, "rgba(255,255,255,1)"); 100 grd1.addColorStop(0, "rgba(255,255,255,0)"); 101 grd1.addColorStop(1, obj.scolor); 102 ctx.fillStyle = grd1; 103 ctx.fill(); 104 ctx.restore(); 105 106 var grd = ctx.createRadialGradient(obj.x - ballR * 3 / 10, obj.y - ballR * 4 / 10, ballR / 8, obj.x - ballR * 4 / 10, obj.y - ballR * 4 / 10, ballR * 16 / 10); 107 grd.addColorStop(0, "rgba(255,255,255,1)"); 108 grd.addColorStop(0.2, "rgba(255,255,255,0)"); 109 grd.addColorStop(1, "rgba(255,255,255,0)"); 110 // grd.addColorStop(1, obj.scolor); 111 ctx.fillStyle = grd; 112 ctx.save(); 113 ctx.shadowColor = 'rgba(0,0,0,.0)'; 114 ctx.fill(); 115 ctx.restore(); 116 } 117 118 function randomBall(num) { 119 var barr = []; 120 var ball; 121 for (var i = 0; i < num || 0; i++) { 122 ball = {}; 123 ball.x = Math.random() * (can.width - ballR * 2) + ballR; 124 ball.y = Math.random() * (can.height - ballR * 2) + ballR; 125 ball.sx = Math.random() * 6 - 6 / 2; 126 ball.sy = Math.random() * 6 - 6 / 2; 127 var scr = Math.round(Math.random() * 200 + 50); 128 var scg; 129 var scb; 130 if (scr > 200) { 131 if (Math.random() > 1) { 132 scg = Math.round(Math.random() * 150 + 50); 133 scb = Math.round(Math.random() * 200 + 50); 134 } else { 135 scb = Math.round(Math.random() * 150 + 50); 136 scg = Math.round(Math.random() * 200 + 50); 137 } 138 } else { 139 scg = Math.round(Math.random() * 200 + 50); 140 scb = Math.round(Math.random() * 200 + 50); 141 } 142 ball.scolor = 'rgba(' + [scr, scg, scb, 1].join(',') + ')'; 143 barr.push(ball); 144 } 145 return barr; 146 } 147 148 //碰撞检测 149 function checkPeng(arr, i) { 150 var j, len; 151 152 for (j = 0, len = arr.length; j < len; j++) { 153 if (i === j) { 154 continue; 155 } 156 var ca = { 157 x: arr[i].x - arr[j].x, 158 y: arr[i].y - arr[j].y 159 } 160 var z = Math.sqrt(Math.pow(ca.x, 2) + Math.pow(ca.y, 2)); 161 var cha = z - ballR * 2; 162 if (cha <= 0) { 163 if (arr[i].x < arr[j].x) { 164 arr[i].x += cha; 165 } else { 166 arr[i].x += -cha; 167 } 168 if (arr[i].y < arr[j].y) { 169 arr[i].y += cha; 170 } else { 171 arr[i].y += -cha; 172 } 173 //arr[i].sy = -1*arr[i].sy; 174 var iTY = arr[i].sy; 175 arr[i].sy = 1 * arr[j].sy; 176 arr[j].sy = iTY; 177 //arr[i].sx = -1*arr[i].sx; 178 var iTX = arr[i].sx; 179 arr[i].sx = 1 * arr[j].sx; 180 arr[j].sx = iTX; 181 } 182 } 183 } 184 } 185 </script> 186 </body> 187 188 </html>
就这样吧,canvas写了一些有意思的demo,但是没有系统的可以写成博客的东西,之后会慢慢整理一下介绍给大家~
最后,祝大家鸡年大吉吧,升职涨薪。