canvas的进阶 - 学习利用canvas做一个炫酷的倒计时功能
先给大家贴一张图片,因为我不会上传视频( ̄□ ̄||) ,请大家谅解了~ 如果有知道怎么上传视频的大神还请指点指点 ^_^ ~

然后看一下代码:
html部分 :
<!DOCTYPE html>
<html lang="en" style="height: 100%"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>倒计时</title>
</head> <body style="height:96%">
<canvas id="canvas" style="height: 100%"></canvas>
</body> </html>
<script src="./digit.js"></script>
然后需要引入来控制小球位置来构成数字,来看一张图片:看到这张图片,想必大家就会明白了我们需要引入的数据结构。

看一下需要引入的digit.js的代码:
digit = [
[
[0, 0, 1, 1, 1, 0, 0],
[0, 1, 1, 0, 1, 1, 0],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 0, 1, 1, 0],
[0, 0, 1, 1, 1, 0, 0],
], //
[
[0, 0, 0, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1],
], //
[
[0, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 1, 1, 1],
], //
[
[1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 1, 1, 1, 0],
], //
[
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 1, 0],
[0, 1, 1, 0, 1, 1, 0],
[1, 1, 0, 0, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1],
], //
[
[1, 1, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 1, 1, 1, 0],
], //
[
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 1, 1, 1, 0],
], //
[
[1, 1, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
], //
[
[0, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 1, 1, 1, 0],
], //
[
[0, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[1, 1, 0, 0, 0, 1, 1],
[0, 1, 1, 1, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 1, 1, 0, 0, 0, 0],
], //
[
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
] // :
]
小球的位置该怎么计算呢?再来看一张图片:

js的代码我就直接粘贴出来了,大部分都已经写上注释了。大家如果还是有地方弄不明白可以去慕课网看刘宇波老师的免费教学视频再学习一下。把地址直接给你们贴出来省去大家搜索的时间。炫丽的倒计时效果Canvas绘图与动画基础
<script>
var WINDOW_WIDTH = undefined; //画布的宽度
var WINDOW_HEIGHT = undefined; //画布的高度
var RADIUS = undefined; //小球的半径
var MARGIN_LEFT = undefined; //数字距离画布上方的距离
var MARGIN_TOP = undefined; //最左边数字距离画布左边的距离 // var endTime = new Date(2019, 5, 28, 08, 30, 30); //设置倒计时终止的时间,此处注意月份是从0开始计算,即0代表1月 var endTime = new Date();
endTime.setTime(endTime.getTime() + 3600 * 1000) //设置一小时的倒计时
var curShowTimeSecoeds = undefined; //现在倒计时有多少毫秒
var balls = []; //存储时间变化时产生的新的小球
var colors = ['#33B5E5', '#0099CC', '#AA66CC', '#9933CC', '#669900', '#FFBB33', '#FF8800', '#FF4444', '#CC0000']; window.onload = function () {
var canvas = document.getElementById('canvas'); WINDOW_WIDTH = document.body.clientWidth;
WINDOW_HEIGHT = document.body.clientHeight; MARGIN_LEFT = Math.round(WINDOW_WIDTH / 10);
MARGIN_TOP = Math.round(WINDOW_HEIGHT / 5);
RADIUS = Math.round(WINDOW_WIDTH * 4 / 5 / 119) - 1; canvas.width = WINDOW_WIDTH;
canvas.height = WINDOW_HEIGHT; if (canvas.getContext("2d")) {
var context = canvas.getContext('2d'); curShowTimeSecoeds = getCurrentShowTimeSeconds(); //定时器
setInterval(
function () {
render(context);
update();
},
50
)
} else {
alert('您的浏览器不支持canvas,请更换浏览器尝试~')
}
} function render(cxt) { //清空一下画布内容
cxt.clearRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); //计算需要倒计时的时分秒
var hours = parseInt(curShowTimeSecoeds / 3600);
var minutes = parseInt((curShowTimeSecoeds - hours * 3600) / 60);
var seconds = curShowTimeSecoeds % 60; //确定时分秒和冒号的数字及位置
renderDigit(MARGIN_LEFT, MARGIN_TOP, parseInt(hours / 10), cxt)
renderDigit(MARGIN_LEFT + 15 * (RADIUS + 1), MARGIN_TOP, parseInt(hours % 10), cxt)
renderDigit(MARGIN_LEFT + 32 * (RADIUS + 1), MARGIN_TOP, 10, cxt)
renderDigit(MARGIN_LEFT + 43 * (RADIUS + 1), MARGIN_TOP, parseInt(minutes / 10), cxt)
renderDigit(MARGIN_LEFT + 59 * (RADIUS + 1), MARGIN_TOP, parseInt(minutes % 10), cxt)
renderDigit(MARGIN_LEFT + 76 * (RADIUS + 1), MARGIN_TOP, 10, cxt)
renderDigit(MARGIN_LEFT + 88 * (RADIUS + 1), MARGIN_TOP, parseInt(seconds / 10), cxt)
renderDigit(MARGIN_LEFT + 104 * (RADIUS + 1), MARGIN_TOP, parseInt(seconds % 10), cxt) //绘制时分秒和冒号的小球的
for (var i = 0; i < balls.length; i++) {
cxt.fillStyle = balls[i].color; cxt.beginPath();
cxt.arc(balls[i].x, balls[i].y, RADIUS, 0, 2 * Math.PI, true);
cxt.closePath(); cxt.fill();
}
} //画时分秒上的小球
function renderDigit(x, y, num, cxt) { cxt.fillStyle = 'rgb(0,102,153)'; for (var i = 0; i < digit[num].length; i++) {
for (var j = 0; j < digit[num][i].length; j++) {
if (digit[num][i][j] === 1) {
cxt.beginPath();
cxt.arc(x + j * 2 * (RADIUS + 1) + (RADIUS + 1), y + i * 2 * (RADIUS + 1) + (RADIUS + 1), RADIUS, 0, 2 * Math.PI);
cxt.closePath(); cxt.fill();
}
}
}
} //计算倒计时的时间
function getCurrentShowTimeSeconds() {
var curTime = new Date(); //当前时间
var ret = endTime.getTime() - curTime.getTime(); //截止时间-当前时间
ret = Math.round(ret / 1000); //需要倒计时的时间 秒 return ret >= 0 ? ret : 0; // //时钟效果
// var ret = curTime.getHours() * 3600 + curTime.getMinutes() * 60 + curTime.getSeconds(); return ret; } //时间发生倒计时的函数
function update() { //下一次显示的时间
var nextShowTimeSeconds = getCurrentShowTimeSeconds(); var nextHours = parseInt(nextShowTimeSeconds / 3600);
var nextMinutes = parseInt((nextShowTimeSeconds - nextHours * 3600) / 60);
var nextSeconds = nextShowTimeSeconds % 60; //现在显示的时间
var curHours = parseInt(curShowTimeSecoeds / 3600);
var curMinutes = parseInt((curShowTimeSecoeds - curHours * 3600) / 60);
var curSeconds = curShowTimeSecoeds % 60; //如果时间发生改变就会在相应位置产生新的彩色小球
if (nextShowTimeSeconds !== curShowTimeSecoeds) { if (parseInt(curHours / 10) !== parseInt(nextHours / 10)) {
addBalls(MARGIN_LEFT + 0, MARGIN_TOP, parseInt(nextHours / 10));
}
if (parseInt(curHours % 10) !== parseInt(nextHours % 10)) {
addBalls(MARGIN_LEFT + 15 * (RADIUS + 1), MARGIN_TOP, parseInt(nextHours % 10));
} if (parseInt(curMinutes / 10) !== parseInt(nextMinutes / 10)) {
addBalls(MARGIN_LEFT + 43 * (RADIUS + 1), MARGIN_TOP, parseInt(nextMinutes / 10));
}
if (parseInt(curMinutes % 10) !== parseInt(nextMinutes % 10)) {
addBalls(MARGIN_LEFT + 59 * (RADIUS + 1), MARGIN_TOP, parseInt(nextMinutes % 10));
} if (parseInt(curSeconds / 10) !== parseInt(nextSeconds / 10)) {
addBalls(MARGIN_LEFT + 88 * (RADIUS + 1), MARGIN_TOP, parseInt(nextSeconds / 10));
}
if (parseInt(curSeconds % 10) !== parseInt(nextSeconds % 10)) {
addBalls(MARGIN_LEFT + 104 * (RADIUS + 1), MARGIN_TOP, parseInt(nextSeconds % 10));
} curShowTimeSecoeds = nextShowTimeSeconds; }
//产生的彩色小球的运动
updateBalls(); } //产生的彩色小球运动的函数
function updateBalls() {
for (var i = 0; i < balls.length; i++) {
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
balls[i].vy += balls[i].g; if (balls[i].y >= WINDOW_HEIGHT - RADIUS) {
balls[i].y = WINDOW_HEIGHT - RADIUS;
balls[i].vy = -balls[i].vy * 0.75;
}
} //优化 小球如果滚出画布就取消这些小球
var cnt = 0;
for (var i = 0; i < balls.length; i++) {
if (balls[i].x + RADIUS > 0 && balls[i].x - RADIUS < WINDOW_WIDTH) {
balls[cnt++] = balls[i]
}
} //为了确保性能可以定义一下最多产生多少彩色小球
while (balls.length > Math.min(2000, cnt)) {
balls.pop();
}
} //时间发生变化的时候产生新的彩色小球的函数
function addBalls(x, y, num) {
for (var i = 0; i < digit[num].length; i++) {
for (var j = 0; j < digit[num][i].length; j++) {
if (digit[num][i][j] === 1) {
var aBall = {
x: x + j * 2 * (RADIUS + 1) + (RADIUS + 1),
y: y + i * 2 * (RADIUS + 1) + (RADIUS + 1),
g: 1.5 + Math.random(),
vx: Math.pow(-1, Math.ceil(Math.random() * 1000)) * 4,
vy: Math.pow(-1, Math.ceil(Math.random() * 1000)) * 4,
color: colors[Math.floor(Math.random() * colors.length)]
}
balls.push(aBall)
}
}
}
// console.log(balls.length)
} </script>
canvas的进阶 - 学习利用canvas做一个炫酷的倒计时功能的更多相关文章
- 在树莓派上用 python 做一个炫酷的天气预报
教大家如何在树莓派上自己动手做一个天气预报.此次教程需要大家有一定的python 基础,没有也没关系,文末我会放出我已写好的代码供大家下载. 首先在开始之前 需要申请高德地图API,去高德地图官网注册 ...
- 利用UIWebView打造一个炫酷的视频背景视图(OC & Swift)
http://www.cocoachina.com/ios/20151023/13860.html 2015-10-6更新:适配 Swift2.0 如有需要,可以通过pjin.elvin@gmail. ...
- 如何利用GitHub设计一个炫酷的个人网站(含代码)
1.在开始制作之前我们先预览一下我的网站吧! 1.方式一: 由于是手机版的所以用手机访问下面的链接体验比较好一点: https://tom-shushu.github.io/MyWeb.github. ...
- 教你用canvas打造一个炫酷的碎片切图效果
前言 今天分享一个炫酷的碎片式切图效果,这个其实在自己的之前的博客上有实现过,本人觉得这个效果还是挺炫酷的,这次还是用我们的canvas来实现,代码量不多,但有些地方还是需要花点时间去理解的,需要点数 ...
- 百度前端技术学院2018笔记 之 利用 CSS animation 制作一个炫酷的 Slider
前言 题目地址 利用 CSS animation 制作一个炫酷的 Slider 思路整理 首先页面包含三种东西 一个是type为radio的input其实就是单选框 二是每个单选框对应的label 三 ...
- 使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能。并且在界面上有radio 的选择内容也要上传
使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能.并且在界面上有radio 的选择内容也要上传 uploadify 插件的 下载和文档地址 ...
- 一个炫酷的Actionbar效果
今天在网上看到一个炫酷的Actionbar效果,一个老外做的DEMO,目前很多流行的app已经加入了这个效果. 当用户初始进入该界面的时候,为一个透明的 ActiionBar ,这样利用充分的空间显示 ...
- 2019基于Hexo快速搭建个人博客,打造一个炫酷博客(1)-奥怪的小栈
本文转载于:奥怪的小栈 这篇文章告诉你如何在2019快速上手搭建一个像我一样的博客:基于HEXO+Github搭建.并完成SEO优化,打造一个炫酷博客. 本站基于HEXO+Github搭建.所以你需要 ...
- Android一个炫酷的树状图组织架构图开源控件实现过程
Android一个炫酷的树状图组织架构图开源控件 文章目录 [1 简介] [2 效果展示] [3 使用步骤] [4 实现基本布局流程] [5 实现自由放缩及拖动] [6 实现添加删除及节点动画] [7 ...
随机推荐
- 分布式事务slides
最近看了<分布式系统概念与设计 第 5 版>的分布式事务章节,整理了一份 ppt.还有恢复部分没有收录进来,有空再整理啦. 下面是传到 deckspeaker 上的 slides 展示: ...
- Unable to find a single main class from the following candidates
关于start-class,spring boot官方手册是这么说明的: The plugin rewrites your manifest, and in particular it manages ...
- Notice: Undefined index: user in D:\phpStudy\WWW\js\ls\lsmc\php\add.php on line 9
原文:Notice: Undefined index: user in D:\phpStudy\WWW\js\ls\lsmc\php\add.php on line 9 (初用数据库(mysql)做用 ...
- exponential family distribution(指数族分布)
1. exponential family 给定参数 η,关于 x 的指数族分布定义为如下的形式: p(x∣∣η)=h(x)g(η)exp{ηTu(x)} 其中 x 可以为标量也可以为矢量,可以为离散 ...
- Cocos2dx 温馨提示(十)三种缓存类演示
在介绍了三级缓存,首先,我们必须弄清楚的一个问题:什么是纹理?它的通俗的解释,质感是它的含义的图片. 当图像加载到内存中后,,它是存在于纹理的形式.由于从这里可以看出.纹理事实上就是一块内存.这块内存 ...
- numpy 维度与轴的问题
0. 多维数组的显示问题 >> X = np.reshape(np.arange(24), (2, 3, 4)) # 也即 2 行 3 列的 4 个平面(plane) >> X ...
- Multi-processor having shared memory, private cache memories, and invalidate queues having valid bits and flush bits for serializing transactions
Multi-processor systems are often implemented using a common system bus as the communication mechani ...
- ddraw 视频下绘图 不闪烁的方法
我们假设是在在RGB视频上绘图(直线,矩形等),一般採用双缓冲区继续,使用内存MemoryDC,来实现画的图形在视频上显示不闪烁的功能,可是我们知道用RGB显示视频都是使用GDI进行渲染,这样非常耗C ...
- 大约laravel错误的解决方案
2015-3-13 夜晚 9:13 执行laravel发生错误Indirect modification of overloaded element of BbsArticle has no effe ...
- TL9000 电信业质量体系管理标准
1.背景介绍:1987年国际标准化组织创立了ISO9000标准.标准发布后,在世界范围内得到了迅速的推广和广泛的认可,成为全世界衡量质量管理水平与质量保证能力的公共标准.九十年代,美国三大汽车公司和航 ...