HTML5 网页 上下翻页时钟效果代码

因为博客首页有个Flash的时钟,对于大多数浏览器Flash是没有问题的,而Firefox等就稍微有些麻烦了,而且IOS系统是Flash的死对头。很早之前就想着上个HTML5时钟来替代这个Flash,今天从一个网站弄了点源码,修改了下,总算完工了。

效果暂且可见:Html5 Clock

不过问题又来了,这个是我整合一个JS,调用不同大小的话又得拆开。拆开的话Http请求次数有增加,还有最严重的一个问题,之前的Flash才4KB,这个整合以后的文件16KB,纠结啊。看看能不能到时候再精简下。

HTML5 网页 上下翻页时钟效果代码

PS:185行的urlSize为显示的宽度,高度自动适应。

代码如下:

<html>
<head></head><body>
<script language="JavaScript" type="text/javascript">
/*****************************************
 *
 *	[No need to change] Cross browser requestAnimationFrame
 *  To know more detail, go to the following link
 *  http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 *
*****************************************/
window.requestAnimFrame = (function(callback) {
	var agent = navigator.userAgent
	if(agent.search(/iPhone/) != -1 || agent.search(/iPod/) != -1 || agent.search(/iPad/) != -1){
		return function(callback) {
			window.setTimeout(callback, 1000 / 60);
		};
	}
	return window.requestAnimationFrame ||
		window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function(callback) {
			window.setTimeout(callback, 1000 / 60);
		};
})();
 
/*****************************************
 *
 *  [No need to change] AnimFrame Constructor
 *  For manageing the plural animation canvases.
 *  Usage:
 *   1. Instantiate this Constructor: var animeFrame = new AnimFrame();
 *   2. Set animation objects extended from AnimCanvas Constructor: animeFrame.push(anim01); animeFrame.push(anim02); ...
 *   3. Call the start method: animeFrame.start();
 *   4. Be able to stop animations by calling the stop method (no used in Clocklinks): animeFrame.stop();
 *
*****************************************/
var AnimFrame = (function(){
	function F(){}
	var stack = [];
	var isAnimating;
 
	F.prototype.push = function(instance){
		stack.push(instance);
	};
	F.prototype.stop = function(){
		isAnimating = false;
	};
	F.prototype.start = function(){
		isAnimating = true;
		init();
		animate();
	};
 
	function init(){
		for(var i=0, l=stack.length; i<l; i++) {
			stack[i].init();
		}
	}
 
	function animate(){
		if(isAnimating) {
			requestAnimFrame(function() {
				animate();
			});
		}
		for(var i=0, l=stack.length; i<l; i++) {
			stack[i].render();
		}
	};
	return F;
})();
 
/*****************************************
 *
 *  [No need to change] AnimCanvas Constructor
 *  This is used as a base of animation canvas.
 *
*****************************************/
var AnimCanvas = (function(){
	/* Constructor */
	function F(){
		this.id;
	    this.canvas;
	    this.context;
		this.time;
	    this.startTime;
		this.fps;
		this.fpsStep;
		this.fpsTime;
	}
 
	/* Public Methods */	
	// setCanvas() is required to call for identifying the canvas to use
	F.prototype.setCanvas = function(canvasId){
		this.id = canvasId;
		this.canvas = document.getElementById(this.id);
		this.context = this.canvas.getContext("2d");
	};
 
	// createCanvas() is required to call for 
	F.prototype.createCanvas = function(width, height){
		this.canvas = document.createElement("canvas");
		this.context = this.canvas.getContext("2d");
		this.canvas.width = width;
		this.canvas.height = height;
	};
 
	// setFps() is arbitrary to change the fps
	// if not called, the canvas is rendered right when animation gets ready
	F.prototype.setFps = function(fps){
		this.fps = fps;
		this.fpsStep = 1000 / fps;
		this.fpsFrame;
	};
 
	// init() is called by the AnimFrame constructor when starting Animation
	F.prototype.init = function(){
		this.startTime = (new Date()).getTime();
	};
 
	// render() is called by the AnimFrame constructor each time to render
	F.prototype.render = function(){
		this.time = (new Date()).getTime() - this.startTime;
 
		if(this.fps){
			var millisecond = this.time % 1000;
			var currentFpsFrame = Math.floor(millisecond / this.fpsStep);
			if(this.fpsFrame != currentFpsFrame){
				this.fpsFrame = currentFpsFrame;
				this.draw();
			}
		} else {
			this.draw();
		}
	};
	return F;
})();
 
/*****************************************
 *
 *	SimpleCanvas Constructor
 *
*****************************************/
var SimpleCanvas = (function(){
	/* Constructor */
	function F(){
		this.id;
	    this.canvas;
	    this.context;
	}
 
	/* Public Methods */	
	// setCanvas() is required to call for identifying the canvas to use
	F.prototype.setCanvas = function(canvasId){
		this.id = canvasId;
		this.canvas = document.getElementById(this.id);
		this.context = this.canvas.getContext("2d");
	};
 
	// createCanvas() is required to call for gerating a new canvas object
	F.prototype.createCanvas = function(width, height){
		this.canvas = document.createElement("canvas");
		this.context = this.canvas.getContext("2d");
		this.canvas.width = width;
		this.canvas.height = height;
	};
 
	// render() is called by the AnimFrame constructor each time to render
	F.prototype.render = function(){
		this.draw();
	};
	return F;
})();
 
// Now is Html5 Clock begin, above all is render frame.
 
function isCanvasSupported(){
	var elem = document.createElement("canvas");
	return !!(elem.getContext && elem.getContext("2d"));
}
var urlClock = 'Clock-Html5';
var urlTimezone = 'CCT';
var urlSize = '271';
var urlTitle = '';
var urlMessage = '';
var urlTarget = '';
var urlFrom = '2014,1,1,0,0,0';
var urlColor = 'gray';
//var adImageUrl = "";
//var redirectUrl = "";
var serverYear = new Date().getFullYear();
var serverMonth = new Date().getMonth();
var serverDay = new Date().getDay();
var serverHour = new Date().getHours();
var serverMinute = new Date().getMinutes();
var serverSecond = new Date().getSeconds();
var serverMillisecond = new Date().getMilliseconds();
var rootPath = "/";
//var adId = "Clock-Html5-AD";
 
/*
 Global valuables
 - urlClock
 - urlTimezone
 - urlColor
 - urlSize
 - serverYear
 - serverMonth
 - serverDay
 - serverHour
 - serverMinute
 - serverSecond
 - serverMillisecond
 */
 
var baseSize = 227;
var srcPath = rootPath + "-008/";
 
document.write('<canvas id="' + urlClock + '" width="' + urlSize + 'px" height="' + urlSize/2.91 + 'px"></canvas>');
 
/*****************************************
 *
 *	Clock Constructor extended by AnimCanvas
 *
*****************************************/
var Clock = (function(){
	/* Constructor */
	function F(){}
 
	/* Inheritance */
	F.prototype = new AnimCanvas();
	F.prototype.__super__ = AnimCanvas.prototype;
	F.prototype.init = function(){
		this.__super__.init.apply(this, arguments);
 
		var servertime = new Date();
		servertime.setYear(serverYear);
		servertime.setMonth(serverMonth - 1);
		servertime.setDate(serverDay);
		servertime.setHours(serverHour);
		servertime.setMinutes(serverMinute);
		servertime.setSeconds(serverSecond);
		unixservertime = servertime.getTime();
	};
 
	/* Private Valuables (don't change the values) */
	var canvas, context, time;
	var unixservertime,
		currenttime;
	var hour,
		minute,
		second,
		millisecond;
	var previousHour,
		previousMinute,
		previousSecond;
	var scaleValue = 1;
 
	/* Private Functions */
	function countTime(){
		currenttime = new Date();
		currenttime.setTime(unixservertime + time);
		hour   = currenttime.getHours();
		minute = currenttime.getMinutes();
		second = currenttime.getSeconds();
		millisecond = currenttime.getMilliseconds()
	}
 
 
	/* Public Methods */
	F.prototype.setScale = function(val){
		scaleValue = val;
	};
	F.prototype.draw = function(){
		canvas = this.canvas;
		context = this.context;
		time = this.time;
 
		/* Clear and save initial setting  */
		context.clearRect(0, 0, canvas.width, canvas.height);
		context.save();
 
		/********* Draw from here *********/
		countTime();
		context.translate(0, canvas.height/2);
		context.scale(scaleValue, scaleValue);
 
		// hour panel
		hourPanel.setNumber(hour);
		context.drawImage(hourPanel.canvas, 0, -hourPanel.canvas.height/2);
 
		// minute panel
		minutePanel.setNumber(minute);
		context.drawImage(minutePanel.canvas, 77, -minutePanel.canvas.height/2);
 
		// second panel
		secondPanel.setNumber(second);
		context.drawImage(secondPanel.canvas, 154, -secondPanel.canvas.height/2);
 
		/********* Revert to initial setting *********/
		context.restore();
	}
	return F;
})();
 
 
 
/*****************************************
 *
 *	ClockPanel Constructor extended by AnimCanvas
 *
*****************************************/
var ClockPanel = (function(){
	/* Constructor */
	function F(){}
 
	/* Inheritance */
	F.prototype = new AnimCanvas();
	F.prototype.__super__ = AnimCanvas.prototype;
	F.prototype.init = function(){
		this.__super__.init.apply(this, arguments);
		this.currentNum = 0;
		this.previousNum = 0;
		this.count = 0;
	};
 
	/* Private Valuables (don't change the values) */
	var canvas, context, time;
	var flipFrame = 10;
 
	/* Public Methods */
	F.prototype.draw = function(){
		canvas = this.canvas;
		context = this.context;
		time = this.time;
 
		/* Clear and save initial setting  */
		context.clearRect(0, 0, canvas.width, canvas.height);
		context.save();
 
		/********* Draw from here *********/
		if(this.currentNum == this.previousNum){
			context.drawImage(this.panelList[this.currentNum].canvas, 0, 0);			
		} else {
			this.count++;
 
			var progress = Math.cos(Math.PI * this.count / flipFrame);
			var currentPanel = this.panelList[this.currentNum].canvas;
			var previousPanel = this.panelList[this.previousNum].canvas;
 
			context.save();
			context.translate(0, currentPanel.height/2);
 
			// Upper Current Panel
			context.drawImage(currentPanel, 0, 0, currentPanel.width, currentPanel.height/2, 0, -currentPanel.height/2, currentPanel.width, currentPanel.height/2);
			// Lower Previous Panel
			context.drawImage(previousPanel, 0, previousPanel.height/2, previousPanel.width, previousPanel.height/2, 0, 0, previousPanel.width, previousPanel.height/2);
 
			if(progress>0){
				// Upper Previous Panel
				context.drawImage(previousPanel, 0, 0, previousPanel.width, previousPanel.height/2, 0, -previousPanel.height/2*progress, previousPanel.width, previousPanel.height/2*progress);
			} else {
				progress = progress* -1;
				// Lower Current Panel
				context.drawImage(currentPanel, 0, currentPanel.height/2, currentPanel.width, currentPanel.height/2, 0, 0, currentPanel.width, currentPanel.height/2*progress);
			}
 
			context.restore();
 
			if(this.count==flipFrame){
				this.count=0;
				this.previousNum = this.currentNum;
			}
 
		}
 
 
		/********* Revert to initial setting *********/
		context.restore();
	}
	F.prototype.setPanelList = function(array){
		this.panelList = array;
	}
 
	F.prototype.setNumber = function(num){
		this.currentNum = num;
	}
	return F;
})();
 
 
/*****************************************
 *
 *	General60 Constructor extended by AnimCanvas
 *
*****************************************/
var General60 = (function(){
	/* Constructor */
	function F(){}
 
	/* Inheritance */
	F.prototype = new SimpleCanvas();
 
	/* Private Valuables */
	var canvas, context, time;
	var corderRound = { x : 10, y : 8 }
 
	/* Public Methods */
	F.prototype.draw = function(){
		canvas = this.canvas;
		context = this.context;
		time = this.time;
 
		/* Clear and save initial setting  */
		context.clearRect(0, 0, canvas.width, canvas.height);
		context.save();
 
		/********* Draw from here *********/
		// Create Clip Path
		context.beginPath();
		context.moveTo(0, corderRound.y);
		context.quadraticCurveTo(0, 0, corderRound.x, 0);
		context.lineTo(canvas.width-corderRound.x, 0);
		context.quadraticCurveTo(canvas.width, 0, canvas.width, corderRound.y);
		context.lineTo(canvas.width, canvas.height-corderRound.y);
		context.quadraticCurveTo(canvas.width, canvas.height, canvas.width-corderRound.x, canvas.height);
		context.lineTo(corderRound.x, canvas.height);
		context.quadraticCurveTo(0, canvas.height, 0, canvas.height-corderRound.y);
		context.closePath();
		// context.clip();
 
		// Fill Background Color
		context.fillStyle = this.color;
		context.fill();
		// context.fillRect(0, 0, canvas.width, canvas.height);
 
		// Draw the Number
		context.font = "62px Arial"
		context.textAlign = "center";
		context.textBaseline = "Alphabetic";
		context.fillStyle = "#ffffff";
		if(this.color.toLowerCase() == "white" || this.color.toLowerCase() == "#ffffff"){
			context.fillStyle = "#000000";
		}
		context.fillText(this.number, canvas.width/2, canvas.height-8.5);
 
		// Draw Center Line
		context.strokeStyle = this.color;
		context.lineWidth = 1;
		context.beginPath();
		context.moveTo(0, canvas.height/2);
		context.lineTo(canvas.width, canvas.height/2);
		context.stroke();
 
		/********* Revert to initial setting *********/
		context.restore();
	}
	F.prototype.setColor = function(color){
		this.color = color.toString();
	}
	F.prototype.setNumber = function(number){
		this.number = number.toString();
		if(this.number.length == 1){
			this.number = "0" + this.number;
		}
	}
	return F;
})();
 
/*****************************************
 *
 *	Hour24 Constructor extended by AnimCanvas
 *
*****************************************/
var Hour24 = (function(){
	/* Constructor */
	function F(){
		this.pm = false;
	}
 
	/* Inheritance */
	F.prototype = new SimpleCanvas();
 
	/* Private Valuables */
	var canvas, context, time;
	var corderRound = { x : 10, y : 8 }
 
	/* Public Methods */
	F.prototype.draw = function(){
		canvas = this.canvas;
		context = this.context;
		time = this.time;
 
		/* Clear and save initial setting  */
		context.clearRect(0, 0, canvas.width, canvas.height);
		context.save();
 
		/********* Draw from here *********/
		// Create Clip Path
		context.beginPath();
		context.moveTo(0, corderRound.y);
		context.quadraticCurveTo(0, 0, corderRound.x, 0);
		context.lineTo(canvas.width-corderRound.x, 0);
		context.quadraticCurveTo(canvas.width, 0, canvas.width, corderRound.y);
		context.lineTo(canvas.width, canvas.height-corderRound.y);
		context.quadraticCurveTo(canvas.width, canvas.height, canvas.width-corderRound.x, canvas.height);
		context.lineTo(corderRound.x, canvas.height);
		context.quadraticCurveTo(0, canvas.height, 0, canvas.height-corderRound.y);
		context.closePath();
		// context.clip();
 
		// Fill Background Color
		context.fillStyle = this.color;
		context.fill();
		// context.fillRect(0, 0, canvas.width, canvas.height);
 
		// Draw the Number
		context.font = "62px Arial"
		context.textAlign = "center";
		context.textBaseline = "Alphabetic";
		context.fillStyle = "#ffffff";
		if(this.color.toLowerCase() == "white" || this.color.toLowerCase() == "#ffffff"){
			context.fillStyle = "#000000";
		}
		context.fillText(this.number, canvas.width/2, canvas.height-8.5);
 
		// Draw the Number
		context.font = "8px Arial"
		context.textAlign = "left";
		if(this.pm){
			context.fillText("PM", 4, canvas.height-8.5);
		} else {
			context.fillText("AM", 4, canvas.height-8.5);
		}
 
		// Draw Center Line
		context.strokeStyle = this.color;
		context.lineWidth = 1;
		context.beginPath();
		context.moveTo(0, canvas.height/2);
		context.lineTo(canvas.width, canvas.height/2);
		context.stroke();	
 
		/********* Revert to initial setting *********/
		context.restore();
	}
	F.prototype.setColor = function(color){
		this.color = color.toString();
	}
	F.prototype.setNumber = function(number){
		this.number = number;
		if(this.number >= 12){
			this.pm = true;
			this.number = this.number - 12
		}
		this.number = this.number != 0 ? this.number : 12;
		this.number = this.number.toString();
	}
	return F;
})();
 
 
/* Create Instance */
var color = urlColor;
switch(urlColor){
	case "black":
		color = "#000000";
		break;
	case "blue":
		color = "#0000ff";
		break;
	case "gray":
		color = "#808080";
		break;
	case "green":
		color = "#008000";
		break;
	case "orange":
		color = "#ffa500";
		break;
	case "pink":
		color = "#ffc0cb";
		break;
	case "red":
		color = "#ff0000";
		break;
	case "white":
		color = "#ffffff";
		break;
}
 
var generalNum = [];
var hourNum = [];
 
for(var i=0; i<60; i++){
	var num = new General60();
	num.createCanvas(73, 61);
	num.setColor(color);
	num.setNumber(i);
	num.render();
	generalNum.push(num);
}
for(var i=0; i<24; i++){
	var num = new Hour24();
	num.createCanvas(73, 61);
	num.setColor(color);
	num.setNumber(i);
	num.render();
	hourNum.push(num);
}
 
var hourPanel = new ClockPanel();
hourPanel.createCanvas(73, 61);
hourPanel.setFps(30);
hourPanel.setPanelList(hourNum);
 
var minutePanel = new ClockPanel();
minutePanel.createCanvas(73, 61);
minutePanel.setFps(30);
minutePanel.setPanelList(generalNum);
 
var secondPanel = new ClockPanel();
secondPanel.createCanvas(73, 61);
secondPanel.setFps(30);
secondPanel.setPanelList(generalNum);
 
var clock = new Clock();
clock.setCanvas(urlClock);
clock.setScale(urlSize/baseSize);
 
/* Start Animation */
var animFrame = new AnimFrame();
animFrame.push(clock);
animFrame.push(hourPanel);
animFrame.push(minutePanel);
animFrame.push(secondPanel);
animFrame.start();
</script>
 
</body>
</html>

教程来自:onedou