canvas的进阶 - 学习利用canvas做一个炫酷的倒计时功能
先给大家贴一张图片,因为我不会上传视频( ̄□ ̄||) ,请大家谅解了~ 如果有知道怎么上传视频的大神还请指点指点 ^_^ ~
然后看一下代码:
html部分 :
1 <!DOCTYPE html> 2 <html lang="en" style="height: 100%"> 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>倒计时</title> 9 </head> 10 11 <body style="height:96%"> 12 <canvas id="canvas" style="height: 100%"></canvas> 13 </body> 14 15 </html> 16 <script src="./digit.js"></script>
然后需要引入来控制小球位置来构成数字,来看一张图片:看到这张图片,想必大家就会明白了我们需要引入的数据结构。
看一下需要引入的digit.js的代码:
1 digit = [ 2 [ 3 [0, 0, 1, 1, 1, 0, 0], 4 [0, 1, 1, 0, 1, 1, 0], 5 [1, 1, 0, 0, 0, 1, 1], 6 [1, 1, 0, 0, 0, 1, 1], 7 [1, 1, 0, 0, 0, 1, 1], 8 [1, 1, 0, 0, 0, 1, 1], 9 [1, 1, 0, 0, 0, 1, 1], 10 [1, 1, 0, 0, 0, 1, 1], 11 [0, 1, 1, 0, 1, 1, 0], 12 [0, 0, 1, 1, 1, 0, 0], 13 ], //0 14 [ 15 [0, 0, 0, 1, 1, 0, 0], 16 [0, 1, 1, 1, 1, 0, 0], 17 [0, 0, 0, 1, 1, 0, 0], 18 [0, 0, 0, 1, 1, 0, 0], 19 [0, 0, 0, 1, 1, 0, 0], 20 [0, 0, 0, 1, 1, 0, 0], 21 [0, 0, 0, 1, 1, 0, 0], 22 [0, 0, 0, 1, 1, 0, 0], 23 [0, 0, 0, 1, 1, 0, 0], 24 [1, 1, 1, 1, 1, 1, 1], 25 ], //1 26 [ 27 [0, 1, 1, 1, 1, 1, 0], 28 [1, 1, 0, 0, 0, 1, 1], 29 [0, 0, 0, 0, 0, 1, 1], 30 [0, 0, 0, 0, 1, 1, 0], 31 [0, 0, 0, 1, 1, 0, 0], 32 [0, 0, 1, 1, 0, 0, 0], 33 [0, 1, 1, 0, 0, 0, 0], 34 [1, 1, 0, 0, 0, 0, 0], 35 [1, 1, 0, 0, 0, 1, 1], 36 [1, 1, 1, 1, 1, 1, 1], 37 ], //2 38 [ 39 [1, 1, 1, 1, 1, 1, 1], 40 [0, 0, 0, 0, 0, 1, 1], 41 [0, 0, 0, 0, 1, 1, 0], 42 [0, 0, 0, 1, 1, 0, 0], 43 [0, 0, 1, 1, 0, 0, 0], 44 [0, 0, 0, 0, 1, 1, 0], 45 [0, 0, 0, 0, 0, 1, 1], 46 [0, 0, 0, 0, 0, 1, 1], 47 [1, 1, 0, 0, 0, 1, 1], 48 [0, 1, 1, 1, 1, 1, 0], 49 ], //3 50 [ 51 [0, 0, 0, 0, 1, 1, 0], 52 [0, 0, 0, 1, 1, 1, 0], 53 [0, 0, 1, 1, 1, 1, 0], 54 [0, 1, 1, 0, 1, 1, 0], 55 [1, 1, 0, 0, 1, 1, 0], 56 [1, 1, 1, 1, 1, 1, 1], 57 [0, 0, 0, 0, 1, 1, 0], 58 [0, 0, 0, 0, 1, 1, 0], 59 [0, 0, 0, 0, 1, 1, 0], 60 [0, 0, 0, 1, 1, 1, 1], 61 ], //4 62 [ 63 [1, 1, 1, 1, 1, 1, 1], 64 [1, 1, 0, 0, 0, 0, 0], 65 [1, 1, 0, 0, 0, 0, 0], 66 [1, 1, 1, 1, 1, 1, 0], 67 [0, 0, 0, 0, 0, 1, 1], 68 [0, 0, 0, 0, 0, 1, 1], 69 [0, 0, 0, 0, 0, 1, 1], 70 [0, 0, 0, 0, 0, 1, 1], 71 [1, 1, 0, 0, 0, 1, 1], 72 [0, 1, 1, 1, 1, 1, 0], 73 ], //5 74 [ 75 [0, 0, 0, 0, 1, 1, 0], 76 [0, 0, 1, 1, 0, 0, 0], 77 [0, 1, 1, 0, 0, 0, 0], 78 [1, 1, 0, 0, 0, 0, 0], 79 [1, 1, 0, 1, 1, 1, 0], 80 [1, 1, 0, 0, 0, 1, 1], 81 [1, 1, 0, 0, 0, 1, 1], 82 [1, 1, 0, 0, 0, 1, 1], 83 [1, 1, 0, 0, 0, 1, 1], 84 [0, 1, 1, 1, 1, 1, 0], 85 ], //6 86 [ 87 [1, 1, 1, 1, 1, 1, 1], 88 [1, 1, 0, 0, 0, 1, 1], 89 [0, 0, 0, 0, 1, 1, 0], 90 [0, 0, 0, 0, 1, 1, 0], 91 [0, 0, 0, 1, 1, 0, 0], 92 [0, 0, 0, 1, 1, 0, 0], 93 [0, 0, 1, 1, 0, 0, 0], 94 [0, 0, 1, 1, 0, 0, 0], 95 [0, 0, 1, 1, 0, 0, 0], 96 [0, 0, 1, 1, 0, 0, 0], 97 ], //7 98 [ 99 [0, 1, 1, 1, 1, 1, 0], 100 [1, 1, 0, 0, 0, 1, 1], 101 [1, 1, 0, 0, 0, 1, 1], 102 [1, 1, 0, 0, 0, 1, 1], 103 [0, 1, 1, 1, 1, 1, 0], 104 [1, 1, 0, 0, 0, 1, 1], 105 [1, 1, 0, 0, 0, 1, 1], 106 [1, 1, 0, 0, 0, 1, 1], 107 [1, 1, 0, 0, 0, 1, 1], 108 [0, 1, 1, 1, 1, 1, 0], 109 ], //8 110 [ 111 [0, 1, 1, 1, 1, 1, 0], 112 [1, 1, 0, 0, 0, 1, 1], 113 [1, 1, 0, 0, 0, 1, 1], 114 [1, 1, 0, 0, 0, 1, 1], 115 [0, 1, 1, 1, 0, 1, 1], 116 [0, 0, 0, 0, 0, 1, 1], 117 [0, 0, 0, 0, 0, 1, 1], 118 [0, 0, 0, 0, 1, 1, 0], 119 [0, 0, 0, 1, 1, 0, 0], 120 [0, 1, 1, 0, 0, 0, 0], 121 ], //9 122 [ 123 [0, 0, 0, 0], 124 [0, 0, 0, 0], 125 [0, 1, 1, 0], 126 [0, 1, 1, 0], 127 [0, 0, 0, 0], 128 [0, 0, 0, 0], 129 [0, 1, 1, 0], 130 [0, 1, 1, 0], 131 [0, 0, 0, 0], 132 [0, 0, 0, 0], 133 ] // : 134 ]
小球的位置该怎么计算呢?再来看一张图片:
js的代码我就直接粘贴出来了,大部分都已经写上注释了。大家如果还是有地方弄不明白可以去慕课网看刘宇波老师的免费教学视频再学习一下。把地址直接给你们贴出来省去大家搜索的时间。炫丽的倒计时效果Canvas绘图与动画基础
1 <script> 2 var WINDOW_WIDTH = undefined; //画布的宽度 3 var WINDOW_HEIGHT = undefined; //画布的高度 4 var RADIUS = undefined; //小球的半径 5 var MARGIN_LEFT = undefined; //数字距离画布上方的距离 6 var MARGIN_TOP = undefined; //最左边数字距离画布左边的距离 7 8 // var endTime = new Date(2019, 5, 28, 08, 30, 30); //设置倒计时终止的时间,此处注意月份是从0开始计算,即0代表1月 9 10 var endTime = new Date(); 11 endTime.setTime(endTime.getTime() + 3600 * 1000) //设置一小时的倒计时 12 var curShowTimeSecoeds = undefined; //现在倒计时有多少毫秒 13 var balls = []; //存储时间变化时产生的新的小球 14 var colors = ['#33B5E5', '#0099CC', '#AA66CC', '#9933CC', '#669900', '#FFBB33', '#FF8800', '#FF4444', '#CC0000']; 15 16 17 window.onload = function () { 18 var canvas = document.getElementById('canvas'); 19 20 WINDOW_WIDTH = document.body.clientWidth; 21 WINDOW_HEIGHT = document.body.clientHeight; 22 23 MARGIN_LEFT = Math.round(WINDOW_WIDTH / 10); 24 MARGIN_TOP = Math.round(WINDOW_HEIGHT / 5); 25 RADIUS = Math.round(WINDOW_WIDTH * 4 / 5 / 119) - 1; 26 27 28 canvas.width = WINDOW_WIDTH; 29 canvas.height = WINDOW_HEIGHT; 30 31 if (canvas.getContext("2d")) { 32 var context = canvas.getContext('2d'); 33 34 curShowTimeSecoeds = getCurrentShowTimeSeconds(); 35 36 //定时器 37 setInterval( 38 function () { 39 render(context); 40 update(); 41 }, 42 50 43 ) 44 } else { 45 alert('您的浏览器不支持canvas,请更换浏览器尝试~') 46 } 47 } 48 49 function render(cxt) { 50 51 //清空一下画布内容 52 cxt.clearRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 53 54 //计算需要倒计时的时分秒 55 var hours = parseInt(curShowTimeSecoeds / 3600); 56 var minutes = parseInt((curShowTimeSecoeds - hours * 3600) / 60); 57 var seconds = curShowTimeSecoeds % 60; 58 59 //确定时分秒和冒号的数字及位置 60 renderDigit(MARGIN_LEFT, MARGIN_TOP, parseInt(hours / 10), cxt) 61 renderDigit(MARGIN_LEFT + 15 * (RADIUS + 1), MARGIN_TOP, parseInt(hours % 10), cxt) 62 renderDigit(MARGIN_LEFT + 32 * (RADIUS + 1), MARGIN_TOP, 10, cxt) 63 renderDigit(MARGIN_LEFT + 43 * (RADIUS + 1), MARGIN_TOP, parseInt(minutes / 10), cxt) 64 renderDigit(MARGIN_LEFT + 59 * (RADIUS + 1), MARGIN_TOP, parseInt(minutes % 10), cxt) 65 renderDigit(MARGIN_LEFT + 76 * (RADIUS + 1), MARGIN_TOP, 10, cxt) 66 renderDigit(MARGIN_LEFT + 88 * (RADIUS + 1), MARGIN_TOP, parseInt(seconds / 10), cxt) 67 renderDigit(MARGIN_LEFT + 104 * (RADIUS + 1), MARGIN_TOP, parseInt(seconds % 10), cxt) 68 69 //绘制时分秒和冒号的小球的 70 for (var i = 0; i < balls.length; i++) { 71 cxt.fillStyle = balls[i].color; 72 73 cxt.beginPath(); 74 cxt.arc(balls[i].x, balls[i].y, RADIUS, 0, 2 * Math.PI, true); 75 cxt.closePath(); 76 77 cxt.fill(); 78 } 79 } 80 81 //画时分秒上的小球 82 function renderDigit(x, y, num, cxt) { 83 84 cxt.fillStyle = 'rgb(0,102,153)'; 85 86 for (var i = 0; i < digit[num].length; i++) { 87 for (var j = 0; j < digit[num][i].length; j++) { 88 if (digit[num][i][j] === 1) { 89 cxt.beginPath(); 90 cxt.arc(x + j * 2 * (RADIUS + 1) + (RADIUS + 1), y + i * 2 * (RADIUS + 1) + (RADIUS + 1), RADIUS, 0, 2 * Math.PI); 91 cxt.closePath(); 92 93 cxt.fill(); 94 } 95 } 96 } 97 } 98 99 //计算倒计时的时间 100 function getCurrentShowTimeSeconds() { 101 var curTime = new Date(); //当前时间 102 var ret = endTime.getTime() - curTime.getTime(); //截止时间-当前时间 103 ret = Math.round(ret / 1000); //需要倒计时的时间 秒 104 105 return ret >= 0 ? ret : 0; 106 107 108 // //时钟效果 109 // var ret = curTime.getHours() * 3600 + curTime.getMinutes() * 60 + curTime.getSeconds(); 110 111 return ret; 112 113 114 } 115 116 //时间发生倒计时的函数 117 function update() { 118 119 //下一次显示的时间 120 var nextShowTimeSeconds = getCurrentShowTimeSeconds(); 121 122 var nextHours = parseInt(nextShowTimeSeconds / 3600); 123 var nextMinutes = parseInt((nextShowTimeSeconds - nextHours * 3600) / 60); 124 var nextSeconds = nextShowTimeSeconds % 60; 125 126 //现在显示的时间 127 var curHours = parseInt(curShowTimeSecoeds / 3600); 128 var curMinutes = parseInt((curShowTimeSecoeds - curHours * 3600) / 60); 129 var curSeconds = curShowTimeSecoeds % 60; 130 131 //如果时间发生改变就会在相应位置产生新的彩色小球 132 if (nextShowTimeSeconds !== curShowTimeSecoeds) { 133 134 if (parseInt(curHours / 10) !== parseInt(nextHours / 10)) { 135 addBalls(MARGIN_LEFT + 0, MARGIN_TOP, parseInt(nextHours / 10)); 136 } 137 if (parseInt(curHours % 10) !== parseInt(nextHours % 10)) { 138 addBalls(MARGIN_LEFT + 15 * (RADIUS + 1), MARGIN_TOP, parseInt(nextHours % 10)); 139 } 140 141 if (parseInt(curMinutes / 10) !== parseInt(nextMinutes / 10)) { 142 addBalls(MARGIN_LEFT + 43 * (RADIUS + 1), MARGIN_TOP, parseInt(nextMinutes / 10)); 143 } 144 if (parseInt(curMinutes % 10) !== parseInt(nextMinutes % 10)) { 145 addBalls(MARGIN_LEFT + 59 * (RADIUS + 1), MARGIN_TOP, parseInt(nextMinutes % 10)); 146 } 147 148 if (parseInt(curSeconds / 10) !== parseInt(nextSeconds / 10)) { 149 addBalls(MARGIN_LEFT + 88 * (RADIUS + 1), MARGIN_TOP, parseInt(nextSeconds / 10)); 150 } 151 if (parseInt(curSeconds % 10) !== parseInt(nextSeconds % 10)) { 152 addBalls(MARGIN_LEFT + 104 * (RADIUS + 1), MARGIN_TOP, parseInt(nextSeconds % 10)); 153 } 154 155 curShowTimeSecoeds = nextShowTimeSeconds; 156 157 } 158 //产生的彩色小球的运动 159 updateBalls(); 160 161 } 162 163 //产生的彩色小球运动的函数 164 function updateBalls() { 165 for (var i = 0; i < balls.length; i++) { 166 balls[i].x += balls[i].vx; 167 balls[i].y += balls[i].vy; 168 balls[i].vy += balls[i].g; 169 170 if (balls[i].y >= WINDOW_HEIGHT - RADIUS) { 171 balls[i].y = WINDOW_HEIGHT - RADIUS; 172 balls[i].vy = -balls[i].vy * 0.75; 173 } 174 } 175 176 //优化 小球如果滚出画布就取消这些小球 177 var cnt = 0; 178 for (var i = 0; i < balls.length; i++) { 179 if (balls[i].x + RADIUS > 0 && balls[i].x - RADIUS < WINDOW_WIDTH) { 180 balls[cnt++] = balls[i] 181 } 182 } 183 184 //为了确保性能可以定义一下最多产生多少彩色小球 185 while (balls.length > Math.min(2000, cnt)) { 186 balls.pop(); 187 } 188 } 189 190 //时间发生变化的时候产生新的彩色小球的函数 191 function addBalls(x, y, num) { 192 for (var i = 0; i < digit[num].length; i++) { 193 for (var j = 0; j < digit[num][i].length; j++) { 194 if (digit[num][i][j] === 1) { 195 var aBall = { 196 x: x + j * 2 * (RADIUS + 1) + (RADIUS + 1), 197 y: y + i * 2 * (RADIUS + 1) + (RADIUS + 1), 198 g: 1.5 + Math.random(), 199 vx: Math.pow(-1, Math.ceil(Math.random() * 1000)) * 4, 200 vy: Math.pow(-1, Math.ceil(Math.random() * 1000)) * 4, 201 color: colors[Math.floor(Math.random() * colors.length)] 202 } 203 balls.push(aBall) 204 } 205 } 206 } 207 // console.log(balls.length) 208 } 209 210 211 </script>