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 ...
随机推荐
- Visual Studio for Mac第四预
微软发布Visual Studio for Mac第四预览版 去年 11 月,微软发布了 Visual Studio for Mac 的首个预览版本,并且承诺后续数月会带来更多功能.而今天,随着 Vi ...
- JPEG图像扩展信息读取和修改
最近,项目需要使用jpg图像信息被写入(非水印),经过研究发现,Android已封装的读者jpg图片扩展信息api(ExifInterface). 通讯api住址:http://developer.a ...
- [ACM] POJ 2689 Prime Distance (筛选范围大素数)
Prime Distance Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12811 Accepted: 3420 D ...
- STL之适配器
一,STL适配器简介 1.什么是适配器 STL提供了序列式容器,同时针对序列式容器提供了应用于不同场景的容器适配器,通俗讲适配器就是以序列式容器为底层数据结构,进一步封装了的为适应场景应用的容器.ST ...
- #747 –在WPF程序的触摸操作中使用惯性移动 (Implementing Inertia during Touch Manipulation)
原文:#747 –在WPF程序的触摸操作中使用惯性移动 (Implementing Inertia during Touch Manipulation) 原文地址:https://wpf.2000th ...
- crawler_正则表达式零宽断言
在使用正则表达式时,有时我们需要捕获的内容前后必须是特定内容,但又不捕获这些特定内容的时候,零宽断言就起到作用了. (?=exp):零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp. ...
- Python 实现 淘宝秒杀 聚划算 自己主动提醒 源代码
说明 本实施例可以监视一起购买的成本button,当警报济济一堂花费时间整点到达(音频文件自定义位置)而自己主动跳出页面(URL习惯). 同一时候还能够通过命令行參数自己定义刷新间隔时间(默认0.1s ...
- shell脚本自动化安装LAMP
#!/bin/bash#auto make install LAMP#by authors yehailun #arp和apr-util依赖APR_FILES=apr-1.6.2.tar.gz APR ...
- WPF编游戏系列 之六 动画效果(1)
原文:WPF编游戏系列 之六 动画效果(1) 本篇主要针对界面进行动画效果处理.首先在打开或关闭界面时,使其产生动态效果而不是生硬的显示或消失(如下图).其次在鼠标放到关闭窗口图标上时, ...
- SICP 关于递归迭代的重新理解以及尾递归的引入...
看了线性的递归和迭代以及树形递归迭代这部分的内容,感觉对递归和迭代又有了新的理解...所以记录一下,也算对这部分内容的总结吧. 首先书中提到的递归与迭代和我以前想的有点不一样,我感觉书中提到的递归和迭 ...