canvas学习之华丽小球滚动电子时钟

教程来自 4-3 华丽的小球滚动效果

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>华丽小球滚动时钟</title>
	<style type="text/css">
		* {
			margin:  0;
			padding: 0;
		}
		html, body {
			width: 100%;
			height: 100%;
		}
	</style>
</head>
<body>
	<canvas id="mainCanvas" style="display: block;border: 1px solid #eee;margin: 0 auto;"></canvas>
<!-- digit.js代码在下面 -->
<script type="text/javascript" src="digit.js"></script>
<script type="text/javascript">
	const CANVAS_WIDTH = document.body.clientWidth - 4;
	const CANVAS_HEIGHT = document.body.clientHeight - 4;
	const BALL_ARC_R = 8; // 半径8像素
	const OFF_LEFT = parseInt((CANVAS_WIDTH - (6 * 7 + 2 * 4) * 20)/2);
	const OFF_TOP = 50;
	const BALL_TUPLE = [];
	const COLORS = ["#33B5E5","#0099CC","#AA66CC","#9933CC","#99CC00","#669900","#FFBB33","#FF8800","#FF4444","#CC0000"];
	let animationTimer = null; // 动画定时器
	let lastTimes = {times: 0, hour_t: 0, hour_a: 0, minute_t: 0, minute_a: 0, second_t: 0, second_a: 0}; // 上次时间
	window.onload = () => {
		let canvasDom = document.querySelector('#mainCanvas')
		canvasDom.width = CANVAS_WIDTH;
		canvasDom.height = CANVAS_HEIGHT;
		let ctx = canvasDom.getContext('2d')

		// 动画入口函数
		function animationEntry() {
			renderCanvas(ctx);
			animationTimer = window.requestAnimationFrame(animationEntry);
		}
		animationTimer = window.requestAnimationFrame(animationEntry);
	}

	// 更新帧率
	function updateFPS() {
	}
	
	// 绘画渲染
	function renderCanvas(ctx) {
		let dateObj = new Date();

		let tempTimes = parseInt(dateObj.valueOf()/ 50);
		if (lastTimes.times != tempTimes) {
			let hour = dateObj.getHours();
			let minute = dateObj.getMinutes();
			let second = dateObj.getSeconds();
			let hour_t = parseInt(hour/10)
			let hour_a = parseInt(hour%10)
			let minute_t = parseInt(minute/10)
			let minute_a = parseInt(minute%10)
			let second_t = parseInt(second/10)
			let second_a = parseInt(second%10)
			if (lastTimes.times == 0) {
				lastTimes.hour_t = hour_t
				lastTimes.hour_a = hour_a
				lastTimes.minute_t = minute_t
				lastTimes.minute_a = minute_a
				lastTimes.second_t = second_t
				lastTimes.second_a = second_a
			}
			lastTimes.times = tempTimes;
			// 清理画布
			ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
			
			drawDigit(ctx, OFF_LEFT, OFF_TOP, hour_t, 'rgb(0, 102, 153)', lastTimes.hour_t != hour_t? (lastTimes.hour_t = hour_t,true): false)
			drawDigit(ctx, OFF_LEFT + 140, OFF_TOP, hour_a, 'rgb(0, 102, 153)', lastTimes.hour_a != hour_a? (lastTimes.hour_a = hour_a,true): false)
			drawDigit(ctx, OFF_LEFT + 140 * 2, OFF_TOP, 10, 'rgb(0, 102, 153)')
			drawDigit(ctx, OFF_LEFT + 140 * 2 + 80, OFF_TOP, minute_t, 'rgb(0, 102, 153)', lastTimes.minute_t != minute_t? (lastTimes.minute_t = minute_t,true): false)
			drawDigit(ctx, OFF_LEFT + 140 * 3 + 80, OFF_TOP, minute_a, 'rgb(0, 102, 153)', lastTimes.minute_a != minute_a? (lastTimes.minute_a = minute_a,true): false)
			drawDigit(ctx, OFF_LEFT + 140 * 4 + 80, OFF_TOP, 10, 'rgb(0, 102, 153)')
			drawDigit(ctx, OFF_LEFT + 140 * 4 + 80 * 2, OFF_TOP, second_t, 'rgb(0, 102, 153)', lastTimes.second_t != second_t? (lastTimes.second_t = second_t,true): false)
			drawDigit(ctx, OFF_LEFT + 140 * 5 + 80 * 2, OFF_TOP, second_a, 'rgb(0, 102, 153)', lastTimes.second_a != second_a? (lastTimes.second_a = second_a,true): false)
			// console.log(BALL_TUPLE);
			let j = 0;
			for (let i = 0; i < BALL_TUPLE.length; i++) {
				let item = BALL_TUPLE[i];
				item.x += item.vx;
				item.y += item.vy;
				item.vy += item.vg;
				if (ctx.canvas.height < item.y) {
					item.y = ctx.canvas.height - BALL_ARC_R;
					item.vy *= -0.8;
				}
				if (ctx.canvas.width > (item.x - BALL_ARC_R)  && (item.x + BALL_ARC_R) > 0) {
					BALL_TUPLE[j++] = item;
				}
			}
			// 截取有效小球
			if (BALL_TUPLE.length != j) {
				BALL_TUPLE.splice(j);
			}
			console.log(BALL_TUPLE.length);
			drawBallMotion(ctx);
		}
		

	}

	// 绘画电子时钟
	function drawDigit(ctx, x, y, num, color, isChange = false) {
		ctx.fillStyle = color;
		const PI2 = 2 * Math.PI;
		let nums = digit[num];
		for (let i = 0; i < nums.length; i++) 
			for (let j = 0; j < nums[i].length; j++)
				if (digit[num][i][j] == 1) {
					let ballX = x + (BALL_ARC_R + 1) * ( 2 * j - 1);
					let ballY = y + (BALL_ARC_R + 1) * ( 2 * i - 1);
					if (isChange) {
						BALL_TUPLE.push({
							x: ballX,
							y: ballY,
							vx: Math.pow( -1, Math.ceil( Math.random() * 1000)) * 2,
							vy: -5,
							vg: 1.5 + Math.random(),
							color: COLORS[ Math.floor(Math.random() * COLORS.length)]
						})
					}
					ctx.beginPath();
					ctx.arc(ballX, ballY, BALL_ARC_R, 0, PI2);
					ctx.closePath();
					ctx.fill();
				}
	}

	// 绘画运动小球
	function drawBallMotion(ctx) {
		const PI2 = 2 * Math.PI;
		for (let item of BALL_TUPLE) {
			ctx.fillStyle = item.color;
			ctx.beginPath();
			ctx.arc(item.x, item.y, BALL_ARC_R, 0, PI2);
			ctx.closePath();
			ctx.fill();
		}
	}
</script>
</body>
</html>

在这里插入图片描述

digit.js

const 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,1,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]]];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值