簡單時間實作:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function startTime()
{
var today=new Date()
var h=today.getHours()
var m=today.getMinutes()
var s=today.getSeconds()
// add a zero in front of numbers<10
m=checkTime(m)
s=checkTime(s)
document.getElementById('txt').innerHTML=h+":"+m+":"+s
t=setTimeout('startTime()',500)
}
function checkTime(i)
{
if (i<10)
{i="0" + i}
return i
}
</script>
</head>
<body onload="startTime()">
<div id="txt"></div>
</body>
</html>
時鐘特效代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<meta name="keywords" content="clock">
<meta name="description" content="This is a clock">
<title>Clock</title>
</head>
<body>
<audio id="ticktock">
<source = src="ticktock.mp3" type="audio/mp3">
</audio>
<script type="text/javascript">
/* 年(y)可以用 1-4 個占位符 月(M)、日(d)、時(H,24時)、時(h,12時)、分(m)、秒(s)、季度(q)
可以用 1-2 個占位符 毫秒(S)隻能用 1 個占位符(是 1-3 位數字)
AM或PM隻能用 1 個占位符(是 2 位英文)
上午或下午(T)隻能用 1 個占位符(是 2 位中文)
星期(E)可以用 1-3 個占位符 季度(q)
隻能用 1 個占位符(是 1 位數字) */
Date.prototype.format = function(fmt) {
var map = {
"M+" : this.getMonth() + 1,
//月
"d+" : this.getDate(),
//日
"H+" : this.getHours(),
//24時
/* 上午12時隻代表當天上午的12時,下午的12時代表當天下午的12時,
0時代表第二天的開始,即前面一天12時已過0時開始計算新一天的時間,
雖然說時間上跟前面那一天下午12時重合,但日期已經發生更改,是以不能說0時就是12時 */
"h+" : this.getHours()%12 == 0 ? 12 : this.getHours()%12,
//12時
"m+" : this.getMinutes(),
//分
"s+" : this.getSeconds(),
//秒
"S" : this.getMilliseconds(),
//毫秒
"t" : this.getHours() < 12 ? "AM" : "PM", "T" : this.getHours() < 12 ? "上午" : "下午",
};
var week = { "0" : "日", "1" : "一", "2" : "二", "3" : "三", "4" : "四", "5" : "五", "6" : "六", }
var quarter = { "0" : "一", "1" : "二", "2" : "三", "3" : "四", }
if(/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
}
if(/(E+)/.test(fmt)) {
var weekPreStr;
switch(RegExp.$1.length) {
case 1: weekPreStr = "";
break;
case 2: weekPreStr = "周";
break;
default: weekPreStr = "星期";
break;
}
fmt = fmt.replace(RegExp.$1, weekPreStr + week[this.getDay()]);
}
if(/(q)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, quarter[Math.floor(this.getMonth() / 3)]); }
for(var key in map) {
if(new RegExp("(" + key + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? map[key] : ("00" + map[key]).substr((map[key]+"").length));
}
}
return fmt;
}
</script>
<script type="text/javascript">
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
var halfPI = Math.PI / 2;
var doublePI = Math.PI * 2;
//陰影級别
var shadowBlur = 10;
//陰影寬度
var shadowWidth = 10;
//陰影在X方向上的偏移
var shadowOffsetX = 5;
//陰影在Y方向上的便宜
var shadowOffsetY = 5;
//深色陰影
var shadowDarkColor = "rgba(0,0,0,0.8)";
//淺色陰影
var shadowLightColor = "rgba(0,0,0,0.1)";
//畫布中心到邊緣的内切圓半徑
var canvasRadius = 250;
canvas.width = canvasRadius * 2;
canvas.height = canvasRadius * 2;
//擷取畫布中心的坐标
var cx = canvasRadius;
var cy = canvasRadius;
//時鐘外圈的貝塞爾花紋個數
var bezierPatternCount = 10;
//時鐘外圈的貝塞爾花紋波峰處半徑
var bezierPeakRadius = canvasRadius - 10;
//時鐘外圈的貝塞爾花紋一半的角度
var bezierHalfSpan = doublePI / bezierPatternCount / 2;
//時鐘外圈的貝塞爾花紋底部半徑
var bezierRadius = bezierPeakRadius - 20;
//時鐘外圈的貝塞爾花紋顔色
var bezierPatternColor = "Plum";
//時鐘外圈半徑
var clockBorderRadius = bezierRadius - 10;
//時鐘外圈寬度
var clockBorderWidth = 10;
//時鐘外圈顔色
var clockBorderColor = "Aqua";
//時鐘外圈陰影半徑
var clockBorderShadowRadius = clockBorderRadius - shadowWidth + 1;
//時鐘整數時間刻度線寬
var clockScaleWidth = 2;
//時鐘整數時間刻度外半徑
var clockScaleOuterRadius = clockBorderRadius - shadowWidth;
//時鐘整數時間刻度内半徑
var clockScaleInnerRadius = clockScaleOuterRadius - 20;
//時鐘刻度顔色
var clockScaleColor = "Black";
//時鐘非整數時間處半徑
var clockScaleMiddleRadius = clockScaleOuterRadius - 10;
//時鐘數字半徑
var clockNumRadius = clockBorderShadowRadius - 40;
//時鐘數字字型
var clockNumFont = "25px Arial";
//時鐘數字顔色
var clockNumColor = "black";
//數字日期距中心的垂直距離
var digitalDateMarginCenter = 50;
//數字日期顔色
var digitalDateColor = "Black";
//數字日期字型
var digitalDateFont = "bold 18px Arial";
//數字時間距中心的垂直距離
var digitalTimeMarginCenter = 100;
//數字時間顔色
var digitalTimeColor = "white";
//數字時間背景顔色
var digitalTimeBgColor = "DarkSlateBlue";
//數字時間字型
var digitalTimeFont = "bold 25px Arial";
//數字時間高度的一半
var digitalTimeHeight = 40;
//數字時間分隔線寬度
var digitalTimeSpanLineWidth = 2;
//時鐘中心點内圓的半徑
var clockCenterInnerDotRadius = 7;
//時鐘中心點内圓的顔色
var clockCenterInnerDotColor = "FireBrick";
//時鐘中心點外圓的半徑
var clockCenterOuterDotRadius = 10;
//時鐘中心點外圓的顔色
var clockCenterOuterDotColor = "Maroon";
//時針線寬
var clockNeedleWidth = 5;
//時針半徑
var clockHourNeedleRadius = clockBorderShadowRadius - 120;
//時針顔色
var clockHourNeedleColor = "DarkGreen";
//分針半徑
var clockMinuteNeedleRadius = clockBorderShadowRadius - 80;
//分針顔色
var clockMinuteNeedleColor = "DarkSlateGray";
//秒針半徑
var clockSecondNeedleRadius = clockBorderShadowRadius - 40;
//秒針尾部半徑
var clockSecondNeedleBottomRadius = -20;
//秒針顔色
var clockSecondNeedleColor = "FireBrick";
//畫圓環
function strokeCircle(cx, cy, r) { ctx.beginPath(); ctx.arc(cx, cy, r, 0, doublePI); ctx.stroke(); }
//畫圓
function fillCircle(cx, cy, r) { ctx.beginPath(); ctx.arc(cx, cy, r, 0, doublePI); ctx.fill(); }
//繪制線條
function strokeLine(x1, y1, x2, y2) { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); }
//根據角度和半徑計算圓上相應位置的坐标(最右側為起始角度,順時針方向為正)
function circlePos(cx, cy, theta, radius) {
var pos = { x: cx + radius * Math.cos(theta), y: cy + radius * Math.sin(theta), };
return pos;
}
//在圓環上繪制刻度線
function strokeCircleLine(cx, cy, theta, r1, r2) {
var pos1 = circlePos(cx, cy, theta, r1);
var pos2 = circlePos(cx, cy, theta, r2);
strokeLine(pos1.x, pos1.y, pos2.x, pos2.y);
}
//設定預設陰影
function setShadow(type) {
ctx.lineWidth = shadowWidth;
ctx.shadowBlur = shadowBlur;
ctx.shadowOffsetX = shadowOffsetX;
ctx.shadowOffsetY = shadowOffsetY;
if(type === 1) {
ctx.shadowColor = shadowLightColor;
} else {
ctx.shadowColor = shadowDarkColor;
}
}
//取消陰影
function clearShadow() {
ctx.shadowColor = "rgba(0,0,0,0)";
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
}
//繪制時鐘外圈的貝塞爾花紋
function renderBezierPattern() {
ctx.fillStyle = bezierPatternColor;
ctx.beginPath();
var theta = 0;
//由于circlePos是順時針方向正, 故圈也是順時針方向
var beginPos = circlePos(cx, cy, theta, bezierRadius);
ctx.moveTo(beginPos.x, beginPos.y);
while(theta < doublePI) {
//貝塞爾曲線控制點
var controlTheta = theta + bezierHalfSpan;
var controlPos = circlePos(cx, cy, controlTheta, bezierPeakRadius);
//貝塞爾曲線終止點
var endTheta = controlTheta + bezierHalfSpan;
var endPos = circlePos(cx, cy, endTheta, bezierRadius);
ctx.quadraticCurveTo(controlPos.x, controlPos.y, endPos.x, endPos.y);
theta = endTheta;
}
//繪制圓counterclockwise=false, 即預設是順時針方向
ctx.arc(cx, cy, clockBorderRadius, 0, doublePI, true);
//注意: 兩個相反方向的路徑内部為填充範圍
ctx.fill();
}
//繪制時鐘邊框
function renderClockBorder() {
//畫外框
ctx.strokeStyle = clockBorderColor;
ctx.lineWidth = clockBorderWidth;
strokeCircle(cx, cy, clockBorderRadius);
//畫外框的内陰影
ctx.strokeStyle = shadowLightColor;
setShadow(1); strokeCircle(cx, cy, clockBorderShadowRadius);
clearShadow();
}
//繪制時鐘圓周上的數字和刻度部分
function renderClockNums() {
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = clockNumFont; var span = doublePI / 60;
for(var i = 1, radian = -halfPI + span; i <= 60; i++, radian += span) { if(i % 5 == 0) {
//繪制刻度
ctx.strokeStyle = clockScaleColor;
ctx.lineWidth = clockScaleWidth;
strokeCircleLine(cx, cy, radian, clockScaleInnerRadius, clockScaleOuterRadius);
//繪制數字
var pos = circlePos(cx, cy, radian, clockNumRadius); var num = i / 5;
ctx.fillStyle = clockNumColor; ctx.fillText(num, pos.x, pos.y);
} else {
ctx.strokeStyle = clockScaleColor;
ctx.lineWidth = clockScaleWidth;
strokeCircleLine(cx, cy, radian, clockScaleMiddleRadius, clockScaleOuterRadius);
}
}
}
//繪制數字時鐘
function renderDigital(date) {
//繪制日期
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = digitalDateFont;
ctx.fillStyle = digitalDateColor;
var text = date.format("yyyy年MM月dd日 EEE");
ctx.fillText(text, cx, cy + digitalDateMarginCenter);
//繪制時間
ctx.font = digitalTimeFont; text = date.format(" HH mm ss ");
ctx.fillStyle = digitalTimeBgColor; var textWidth = ctx.measureText(text).width;
var textBgX = cx - textWidth / 2;
var textBgY = cy + digitalTimeMarginCenter - digitalTimeHeight / 2;
ctx.fillRect(textBgX, textBgY, textWidth, digitalTimeHeight);
ctx.fillStyle = digitalTimeColor;
ctx.fillText(text, cx, cy + digitalTimeMarginCenter);
//繪制事件中間的分隔線
ctx.lineWidth = digitalTimeSpanLineWidth;
ctx.strokeStyle = digitalTimeColor;
var textSpan = textWidth / 6;
var leftLineX = cx - textSpan;
strokeLine(leftLineX, textBgY, leftLineX, textBgY + digitalTimeHeight);
var rightLineX = cx + textSpan; strokeLine(rightLineX, textBgY, rightLineX, textBgY + digitalTimeHeight);
}
//繪制時鐘中心最下方紅點
function renderClockCenterOuterDot() {
ctx.fillStyle = clockCenterOuterDotColor; fillCircle(cx, cy, clockCenterOuterDotRadius);
}
//繪制時鐘中心最上方紅點
function renderClockCenterInnerDot() {
ctx.fillStyle = clockCenterInnerDotColor; fillCircle(cx, cy, clockCenterInnerDotRadius);
}
//繪制時鐘指針
function renderClockNeedle(date) {
var hourRadian = date.getHours() % 12 / 12 * doublePI - halfPI;
var minuteRadian = date.getMinutes() / 60 * doublePI - halfPI;
var secondRadian = date.getSeconds() / 60 * doublePI - halfPI;
setShadow();
ctx.lineCap = "round";
ctx.lineWidth = clockNeedleWidth;
ctx.strokeStyle = clockHourNeedleColor;
strokeCircleLine(cx, cy, hourRadian, 0, clockHourNeedleRadius);
ctx.strokeStyle = clockMinuteNeedleColor;
strokeCircleLine(cx, cy, minuteRadian, 0, clockMinuteNeedleRadius);
ctx.strokeStyle = clockSecondNeedleColor;
strokeCircleLine(cx, cy, secondRadian, clockSecondNeedleBottomRadius, clockSecondNeedleRadius);
ctx.lineCap = "square";
clearShadow();
}
function render(date) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
renderBezierPattern();
renderClockBorder();
renderClockNums();
renderDigital(date);
renderClockCenterOuterDot();
renderClockNeedle(date);
renderClockCenterInnerDot();
}
var lastTime = 0;
var audio = document.getElementById("ticktock");
function loop() {
var date = new Date();
var currentTime = date.getTime();
if(currentTime - lastTime >= 1000) {
lastTime = currentTime;
//注意:這裡設0非常關鍵,否則雖然會循環播放,但會從上一次暫停的地方開始播放,造成延遲
audio.currentTime = 0;
audio.play();
render(date);
}
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>