Canvas学习笔记——学习使用Canvas做出炫丽的时钟或倒计时效果/小球掉落效果

Canvas倒计时效果预览图

Canvas倒计时效果预览图

实现难点

1、如何用小球把数字绘制出来

我们把数字变为了一个里面只有0和1的数组,1就代表小球出现的位置。如下所示。
将0-9十个数组组成的大数组命名为Digit,存储在digit.js文件中,之后直接在index文件中引用。

// digit.js
var 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,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]
        ],//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]
        ],//2
    ]
2、绘制数字时遇到半径和距离相关的问题

首先,距离是需要静下心来慢慢算的。最好能在纸上先画出来。在这里我提供一点小建议。

  1. 将半径、数字与数字之间的间隔、圆点之间的间隔设为全局变量,方便修改而且更容易理清关系。
var Radius = 9;
var Gap = 20;
  1. 绘制函数context.arc(x, y, r, start, end)中的xy指的是圆心的坐标,所以一定要记住处理边缘关系时还要考虑到半径。
3、渲染函数功能划分
1// 单个数字绘制函数
// x:绘制起点横坐标
// y: 绘制起点纵坐标
// num: 绘制的数字
// cxt:canvas绘制上下文
function renderDigit(x, y, num, cxt) { }

2// 渲染秒
function renderSeconds(cxt) { }
// 渲染分
function renderMinutes(cxt) { }
// 渲染时
function renderHours(cxt) { }

3// 总体渲染函数
function render(cxt) { }
4、随着当前时间变化

通过new Date()getHours//getMinutes//getSeconds获取到当前时间的时分秒,再重新渲染一遍。
Canvas的渲染速度很快,所以每次循环都可以清空画布然后再重头开始渲染,自然可以看到最新的时间变化。
render()中调用renderHours等函数,renderHours中再调用new Date()

setInterval(() => {
	render();
}, 50)
5、单个小球的运动

首先定义小球的属性

var ball = {
	x: 圆心横坐标,
	y: 圆心纵坐标,
	r: 半径,
	vx: 小球的横向运动速度,
	vy: 小球的纵向运动速度,
	g: 加速度,
	color: 小球的填充颜色
}

绘制出小球与上面的单个数字小球的绘制方法一样,这里详细讲讲小球的运动实现过程。

function updateBall() {
	ball.x += ball.vx;
	ball.y += ball.vy;
	ball.vy += ball.g;
	// 小球掉到画布下边缘时
	if(ball.y >= WINDOW_HEIGHT - ball.r) {
		ball.vy = -ball.vy * Rub; // 小球获得向上的速度,Rub是摩擦系数
		ball.y = WINDOW_HEIGHT - ball.r;
	}
};
// 接着用定时器循环调用方法,可实现动画的效果。
setInterval(() => {
	updateBall();
	renderBall();
}, 50)
6、获取小球所在位置

renderDigit()函数中返回一组渲染出来的小球数组。

// 首先定义全局变量Balls,用于存储返回的小球
var Balls = [];
function renderDigit(x, y, num, cxt) {
  // 每渲染一个数字都会返回一组全新的小球位置数组
  Balls = [];
  var numDigit =  Digit[parseInt(num)];
  for(let i=0; i<numDigit.length; i++) {
    for(let j=0; j<numDigit[i].length; j++) {
      if(numDigit[i][j] == 1) {
        cxt.beginPath();
        cxt.arc(x+(Gap*j), y+(Gap*i), Radius, 0, 2*Math.PI);
        cxt.fillStyle = '#fff';
        cxt.fill();
        Balls.push({
          'x': x+(Gap*j),
          'y': y+(Gap*i),
          'r': Radius + Math.random(),
          'vx': Math.pow( -1 , Math.ceil( Math.random()*1000 ) ) * 4,
          'vy': VY + Math.random()*4,
          'g': ASpeed + Math.random(),
          'color': Colors[parseInt(Colors.length*Math.random())]
        })
      }
    }
  };
}
7、当数字发生变化时产生相应的小球,以及存储需要动画的小球

首先设置一个数组OldNums用来放旧的数字,用于对比数字是否发生变化。数组一共有六个元素,分别对应着时分秒的六位数字。
还要设置一个全局变量foreverBalls,用于存放当前页面上需要产生运动轨迹的小球参数,之后只需要一直循环渲染这个数组就可以。

var OldNums = []; // length = 6
var foreverBalls = [];
renderDigit(Left+Radius+Gap*21+Gap*21, Radius, parseInt(seconds/10), cxt);
// 在更新数组前先作数字是否发生变化的对比
if(oldNums[4] != parseInt(seconds/10) { 
	// 对小球数组Balls操作
	foreverBalls.push(Balls);
}
// 在渲染时分秒的函数最后,更新数组
oldNums[4] = parseInt(seconds/10);
8、多个小球在页面上产生运动轨迹

在原有的render函数中循环foreverBalls并渲染所有小球,然后在定时器中调用updateBall()方法。

  setInterval(() => {
    render(cxt);
    updateBubble();
  }, 50)
9、优化
  1. foreverBalls数组一直被添加小球,所以需要渲染的小球就会越来越多,所以我们需要当小球数量过多时,删除掉一些看不到但一直在运动的小球。
//防止数组中球的数量太多
function clearBall() {
  if(foreverBall.length>60) {
    foreverBall.splice(0, 30);
  }
}
  1. 页面最小化到后台会产生堆积小球的情况,未解决。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值