看了jscode的《HTML5编程百例之一:HTML5时钟》,很赞!不过有一些地方觉得不太合理,就自己动手重构了下,欢迎大家拍砖!
改进的地方有:
1、不用反复重绘不变的圆盘、刻度和数字;
2、封装了一下;
效果图:
00:00:00
插入文件的功能用不了,只有贴出源代码了,郁闷。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>超酷HTML5时钟(作者:http://www.cnblogs.com/jscode/)</title>
<style type="text/css">
.time {
background: white;
position: absolute;
top: 5px;
left: 130px;
height: 18px;
140px;
opacity: 0.4;
}
</style>
</head>
<body>
<h1>超酷HTML5时钟(作者:http://www.cnblogs.com/jscode/)</h1>
<canvas id="clock" width="400px" height="400px"></canvas>
<div class="time"><span id="currtime">00:00:00</span><em></em></div>
</body>
</html>
<script type="text/javascript">
(function(window, canvasID){
if(window.Clock){
return null;
}
window.Clock = (function(window, canvasID){
function Clock(canvasID){
this.date = new Date();
this.id = canvasID;
this.canvas = window.document.getElementById("clock");
this.context = this.canvas.getContext("2d");
this.radius = Math.min(this.canvas.width / 2, this.canvas.height / 2) - 25;
this.center = {x: this.canvas.width/2, y: this.canvas.height/2};
this.defaultStyle = {fill: "#EFEFEF", stroke: "#000"};
this.hourStyle = {lineWidth: 8, length: this.radius - 10 };
this.minuteStyle = {lineWidth: 5, length: this.radius - 20 };
this.secondStyle = {lineWidth: 3, length: this.radius - 30 };
this.dialStyle = {lineWidth:18};//表盘
this.scaleStyle = { thin: {lineWidth:1}, wide: {lineWidth:3} };//刻度
this.backStyle = { font: "bold 20px 宋体" };
}
Clock.prototype.drawBackground = function(){
var context = this.context;
context.save();
context.lineWidth = this.dialStyle.lineWidth;
context.fillStyle = this.backStyle.fill || this.defaultStyle.fill;
context.strokeStyle = this.backStyle.stroke || this.defaultStyle.stroke;
context.beginPath();
context.arc(this.center.x, this.center.y, this.radius, 0, Math.PI * 2, 0);
context.stroke();
context.fill();
context.closePath();
context.restore();
context.fillStyle = this.backStyle.fill || this.defaultStyle.fill;
context.strokeStyle = this.backStyle.stroke || this.defaultStyle.stroke;
for (var i = 0; i < 30; i++) {
context.save();
context.lineWidth = i%5 === 0 ? this.scaleStyle.wide.lineWidth : this.scaleStyle.thin.lineWidth;
context.beginPath();
context.moveTo(this.center.x + (this.radius-6) * Math.cos((i + 30) * 6 * Math.PI / 180), this.center.y - (this.radius-5) * Math.sin((i + 30) * 6 * Math.PI / 180));
context.lineTo(this.center.x + (this.radius-6) * Math.cos(i * 6 * Math.PI / 180), this.center.y - (this.radius-5) * Math.sin(i * 6 * Math.PI / 180));
context.fill();
context.stroke();
context.closePath();
context.restore();
}
context.moveTo(this.center.x, this.center.y);
context.save();
context.fillStyle = this.backStyle.fill;
context.beginPath();
context.arc(this.center.x, this.center.y, this.radius-16, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
var r = this.radius - 25;
context.fillStyle = this.defaultStyle.stroke;
context.font = this.backStyle.font;
var jiaodu = 0;
for ( var i=1, step=30; i < 13; i++ ) {
if( i <= 3 ){
jiaodu = 90 - i*30;
} else {
jiaodu = 360 - (i - 3)*30;
}
this.drawtext(i, this.center.x + (Math.cos(jiaodu * Math.PI / 180) * r), this.center.y - (Math.sin(jiaodu * Math.PI / 180) * r));
}
context.moveTo(this.center.x, this.center.y);
context.save();
context.fillStyle = this.defaultStyle.stroke;
context.beginPath();
context.arc(this.center.x, this.center.y, 10, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
};
Clock.prototype.drawtext = function(content, x, y) {
content = content.toString()
var context = this.context;
context.save();
x -= (context.measureText(content).width / 2);
y += 9;
context.beginPath();
context.translate(x, y);
context.fillText(content, 0, 0);
context.restore();
};
Clock.prototype.drawHands = function(){
var hour = this.date.getHours() % 12;
var minute = this.date.getMinutes();
var second = this.date.getSeconds();
var paddingLeft = function( n ){
return n.toString().length == 1 ? n.toPrecision(2).toString().split(".").reverse().join("") : n.toString();
};
document.getElementById("currtime").innerHTML = [].concat(paddingLeft(hour), paddingLeft(minute), paddingLeft(second)).join(":");
var hourJiaodu = hour * 30 * Math.PI / 180 + (minute / 60) * 30 * Math.PI / 180 + 90 * Math.PI / 180;
var minuteJiaodu = minute * 6 * Math.PI / 180 + second / 60 * 6 * Math.PI / 180 + 90 * Math.PI / 180;
var secondJiaodu = second * 6 * Math.PI / 180 + 90 * Math.PI / 180;
this.drawHand(this.hourStyle, hourJiaodu, 110);
this.drawHand(this.minuteStyle, minuteJiaodu, 60);
this.drawHand(this.secondStyle, secondJiaodu, 40);
};
Clock.prototype.drawHand = function(style, jiaodu, step){
var context = this.context;
context.save();
context.lineWidth = style.lineWidth || this.defaultStyle.lineWidth;
context.fillStyle = style.fill || this.defaultStyle.fill;
context.strokeStyle = style.stroke || this.defaultStyle.stroke;
context.beginPath();
context.moveTo(this.center.x + 20 * Math.cos(jiaodu), this.center.y + 20 * Math.sin(jiaodu));
context.lineTo(this.center.x - (this.radius - step) * Math.cos(jiaodu), this.center.y - (this.radius - step) * Math.sin(jiaodu));
context.closePath();
context.fill();
context.stroke();
context.restore();
};
Clock.prototype.reset = function(){
var context = this.context;
//清空指针
context.save();
context.lineWidth = 0;
context.fillStyle = this.defaultStyle.fill;
context.beginPath();
context.arc(this.center.x, this.center.y, this.radius-38, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
//绘制圆心
context.save();
context.fillStyle = this.defaultStyle.stroke;
context.beginPath();
context.arc(this.center.x, this.center.y, 10, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
};
Clock.prototype.draw = function(){
this.date = new Date();
this.reset();
this.drawHands();
};
Clock.prototype.run = function(){
this.drawBackground();
var that = this;
setInterval(function(){
Clock.prototype.draw.apply(that)
}, 1000);
};
return new Clock(canvasID);
})(window, canvasID);
window.Clock.run();
})(window, "clock");
</script>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>超酷HTML5时钟(作者:http://www.cnblogs.com/jscode/)</title>
<style type="text/css">
.time {
text-align: center;
400px;
font-family: "Book Antiqua",Palatino,serif;
font-size: 40px;
font-weight: bold;
text-shadow: 1px 1px 3px #333;
position:absolute;
}
.time em {background: white;
position: absolute;
top: 5px;
left: 130px;
height: 18px;
140px;
opacity: 0.4;
}
</style>
</head>
<body>
<h1>超酷HTML5时钟(作者:http://www.cnblogs.com/jscode/)</h1>
<canvas id="clock" width="400px" height="400px"></canvas>
<div class="time"><span id="currtime">00:00:00</span><em></em></div>
</body>
</html>
<script type="text/javascript">
(function(window, canvasID){
if(window.Clock){
return null;
}
window.Clock = (function(window, canvasID){
function Clock(canvasID){
this.date = new Date();
this.id = canvasID;
this.canvas = window.document.getElementById("clock");
this.context = this.canvas.getContext("2d");
this.radius = Math.min(this.canvas.width / 2, this.canvas.height / 2) - 25;
this.center = {x: this.canvas.width/2, y: this.canvas.height/2};
this.defaultStyle = {fill: "#EFEFEF", stroke: "#000"};
this.hourStyle = {lineWidth: 8, length: this.radius - 10 };
this.minuteStyle = {lineWidth: 5, length: this.radius - 20 };
this.secondStyle = {lineWidth: 3, length: this.radius - 30 };
this.dialStyle = {lineWidth:18};//表盘
this.scaleStyle = { thin: {lineWidth:1}, wide: {lineWidth:3} };//刻度
this.backStyle = { font: "bold 20px 宋体" };
}
Clock.prototype.drawBackground = function(){
var context = this.context;
context.save();
context.lineWidth = this.dialStyle.lineWidth;
context.fillStyle = this.backStyle.fill || this.defaultStyle.fill;
context.strokeStyle = this.backStyle.stroke || this.defaultStyle.stroke;
context.beginPath();
context.arc(this.center.x, this.center.y, this.radius, 0, Math.PI * 2, 0);
context.stroke();
context.fill();
context.closePath();
context.restore();
context.fillStyle = this.backStyle.fill || this.defaultStyle.fill;
context.strokeStyle = this.backStyle.stroke || this.defaultStyle.stroke;
for (var i = 0; i < 30; i++) {
context.save();
context.lineWidth = i%5 === 0 ? this.scaleStyle.wide.lineWidth : this.scaleStyle.thin.lineWidth;
context.beginPath();
context.moveTo(this.center.x + (this.radius-6) * Math.cos((i + 30) * 6 * Math.PI / 180), this.center.y - (this.radius-5) * Math.sin((i + 30) * 6 * Math.PI / 180));
context.lineTo(this.center.x + (this.radius-6) * Math.cos(i * 6 * Math.PI / 180), this.center.y - (this.radius-5) * Math.sin(i * 6 * Math.PI / 180));
context.fill();
context.stroke();
context.closePath();
context.restore();
}
context.moveTo(this.center.x, this.center.y);
context.save();
context.fillStyle = this.backStyle.fill;
context.beginPath();
context.arc(this.center.x, this.center.y, this.radius-16, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
var r = this.radius - 25;
context.fillStyle = this.defaultStyle.stroke;
context.font = this.backStyle.font;
var jiaodu = 0;
for ( var i=1, step=30; i < 13; i++ ) {
if( i <= 3 ){
jiaodu = 90 - i*30;
} else {
jiaodu = 360 - (i - 3)*30;
}
this.drawtext(i, this.center.x + (Math.cos(jiaodu * Math.PI / 180) * r), this.center.y - (Math.sin(jiaodu * Math.PI / 180) * r));
}
context.moveTo(this.center.x, this.center.y);
context.save();
context.fillStyle = this.defaultStyle.stroke;
context.beginPath();
context.arc(this.center.x, this.center.y, 10, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
};
Clock.prototype.drawtext = function(content, x, y) {
content = content.toString()
var context = this.context;
context.save();
x -= (context.measureText(content).width / 2);
y += 9;
context.beginPath();
context.translate(x, y);
context.fillText(content, 0, 0);
context.restore();
};
Clock.prototype.drawHands = function(){
var hour = this.date.getHours() % 12;
var minute = this.date.getMinutes();
var second = this.date.getSeconds();
var paddingLeft = function( n ){
return n.toString().length == 1 ? n.toPrecision(2).toString().split(".").reverse().join("") : n.toString();
};
document.getElementById("currtime").innerHTML = [].concat(paddingLeft(hour), paddingLeft(minute), paddingLeft(second)).join(":");
var hourJiaodu = hour * 30 * Math.PI / 180 + (minute / 60) * 30 * Math.PI / 180 + 90 * Math.PI / 180;
var minuteJiaodu = minute * 6 * Math.PI / 180 + second / 60 * 6 * Math.PI / 180 + 90 * Math.PI / 180;
var secondJiaodu = second * 6 * Math.PI / 180 + 90 * Math.PI / 180;
this.drawHand(this.hourStyle, hourJiaodu, 110);
this.drawHand(this.minuteStyle, minuteJiaodu, 60);
this.drawHand(this.secondStyle, secondJiaodu, 40);
};
Clock.prototype.drawHand = function(style, jiaodu, step){
var context = this.context;
context.save();
context.lineWidth = style.lineWidth || this.defaultStyle.lineWidth;
context.fillStyle = style.fill || this.defaultStyle.fill;
context.strokeStyle = style.stroke || this.defaultStyle.stroke;
context.beginPath();
context.moveTo(this.center.x + 20 * Math.cos(jiaodu), this.center.y + 20 * Math.sin(jiaodu));
context.lineTo(this.center.x - (this.radius - step) * Math.cos(jiaodu), this.center.y - (this.radius - step) * Math.sin(jiaodu));
context.closePath();
context.fill();
context.stroke();
context.restore();
};
Clock.prototype.reset = function(){
var context = this.context;
//清空指针
context.save();
context.lineWidth = 0;
context.fillStyle = this.defaultStyle.fill;
context.beginPath();
context.arc(this.center.x, this.center.y, this.radius-38, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
//绘制圆心
context.save();
context.fillStyle = this.defaultStyle.stroke;
context.beginPath();
context.arc(this.center.x, this.center.y, 10, 0, Math.PI * 2, 0);
context.fill();
context.closePath();
context.restore();
};
Clock.prototype.draw = function(){
this.date = new Date();
this.reset();
this.drawHands();
};
Clock.prototype.run = function(){
this.drawBackground();
var that = this;
setInterval(function(){
Clock.prototype.draw.apply(that)
}, 1000);
};
return new Clock(canvasID);
})(window, canvasID);
window.Clock.run();
})(window, "clock");
</script>