先给大家贴一张图片,因为我不会上传视频( ̄□ ̄||) ,请大家谅解了~  如果有知道怎么上传视频的大神还请指点指点 ^_^ ~

然后看一下代码:

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做一个炫酷的倒计时功能的更多相关文章

  1. 在树莓派上用 python 做一个炫酷的天气预报

    教大家如何在树莓派上自己动手做一个天气预报.此次教程需要大家有一定的python 基础,没有也没关系,文末我会放出我已写好的代码供大家下载. 首先在开始之前 需要申请高德地图API,去高德地图官网注册 ...

  2. 利用UIWebView打造一个炫酷的视频背景视图(OC & Swift)

    http://www.cocoachina.com/ios/20151023/13860.html 2015-10-6更新:适配 Swift2.0 如有需要,可以通过pjin.elvin@gmail. ...

  3. 如何利用GitHub设计一个炫酷的个人网站(含代码)

    1.在开始制作之前我们先预览一下我的网站吧! 1.方式一: 由于是手机版的所以用手机访问下面的链接体验比较好一点: https://tom-shushu.github.io/MyWeb.github. ...

  4. 教你用canvas打造一个炫酷的碎片切图效果

    前言 今天分享一个炫酷的碎片式切图效果,这个其实在自己的之前的博客上有实现过,本人觉得这个效果还是挺炫酷的,这次还是用我们的canvas来实现,代码量不多,但有些地方还是需要花点时间去理解的,需要点数 ...

  5. 百度前端技术学院2018笔记 之 利用 CSS animation 制作一个炫酷的 Slider

    前言 题目地址 利用 CSS animation 制作一个炫酷的 Slider 思路整理 首先页面包含三种东西 一个是type为radio的input其实就是单选框 二是每个单选框对应的label 三 ...

  6. 使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能。并且在界面上有radio 的选择内容也要上传

    使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能.并且在界面上有radio 的选择内容也要上传 uploadify 插件的 下载和文档地址  ...

  7. 一个炫酷的Actionbar效果

    今天在网上看到一个炫酷的Actionbar效果,一个老外做的DEMO,目前很多流行的app已经加入了这个效果. 当用户初始进入该界面的时候,为一个透明的 ActiionBar ,这样利用充分的空间显示 ...

  8. 2019基于Hexo快速搭建个人博客,打造一个炫酷博客(1)-奥怪的小栈

    本文转载于:奥怪的小栈 这篇文章告诉你如何在2019快速上手搭建一个像我一样的博客:基于HEXO+Github搭建.并完成SEO优化,打造一个炫酷博客. 本站基于HEXO+Github搭建.所以你需要 ...

  9. Android一个炫酷的树状图组织架构图开源控件实现过程

    Android一个炫酷的树状图组织架构图开源控件 文章目录 [1 简介] [2 效果展示] [3 使用步骤] [4 实现基本布局流程] [5 实现自由放缩及拖动] [6 实现添加删除及节点动画] [7 ...

随机推荐

  1. 一次解决React+TypeScript+Webpack 别名(alias)找不到问题的过程「转载」

    链接 引言 在组件开发中,业务功能和基础组件一般分开放,比如在我们的项目中,components为基础组件, container为业务组件,但是在container中调用components中的组件时 ...

  2. Swift过程控制和功能

    流量控制(Control Flow) For周期 for骑自行车和C语言,OC用法很相似,平时for()和 for in两种. 遍历可以使用下划线"_"略对值的訪问等. Switc ...

  3. sql获取数据库的所有表以及名称字段

    获取数据库中所有的表 SELECT SysObjects.name AS Tablename FROM sysobjects WHERE xtype = 'U' 获取数据库中所有表的列名 SELECT ...

  4. DM365 IPNC软件架构具体解释

    于2013在上半场 - 年DM365.DM368的IPNC(网络摄像机)与稳定性测试工作产品结束. 1.简单介绍: TI针对TMS320DM365.DM368进行了DVR和IPNC的应用方案參考.DV ...

  5. 张量(tensor)的理解

    1. 从标量到矢量:携带更丰富的信息 矢,是箭的意思,突出的特点是其指向性. 袋子里有几个球? 3 个,magnitude(幅度,没有单位): 从这到你家多远?3 km(denominate),3 称 ...

  6. SecureCRT下载/注册/安装镜像文件

    #$language = "VBScript" #$interface = "1.0" ' This automatically generated scrip ...

  7. Haroopad 安装到 Mac OSX

    打开Terminal 控制台 粘贴运行代码安装换cask: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ ...

  8. C++异常机制的实现方式和开销分析 (大图,编译器会为每个函数增加EHDL结构,组成一个单向链表,非常著名的“内存访问违例”出错对话框就是该机制的一种体现)

    白杨 http://baiy.cn 在我几年前开始写<C++编码规范与指导>一文时,就已经规划着要加入这样一篇讨论 C++ 异常机制的文章了.没想到时隔几年以后才有机会把这个尾巴补完 :- ...

  9. WPF学习笔记:(二)数据绑定模式与INotifyPropertyChanged接口

    数据绑定模式共有四种:OneTime.OneWay.OneWayToSource和TwoWay,默认是TwoWay.一般来说,完成数据绑定要有三个要点:目标属性是依赖属性.绑定设置和实现了INotif ...

  10. Java之nio MappedByteBuffer的资源释放问题

    使用nio的MappedByteBuffer映射内存, 在最后执行File.delete()方法的时候, 返回false,  即文件没有被删除. 原因是MappedByteBuffer在内存中也会创建 ...