전에 MDN 의 Canvas 튜토리얼에 나오는 시계를 보고 따라 만들어 본적이 있는데(링크), 이번에는 w3schools의 시계를 보고 따라서 만들어 봤습니다. 코드는 좀 바꿔봤는데, 레이어를 사용해서 시계의 바늘부분만 갱신을 해줍니다.
<!DOCTYPE html>
<style>
.layerBox { display: inline-block; position: relative; }
.layerBox canvas { max-width: 100%; }
#layer1 { vertical-align: top; background: #333; }
#layer2 { position: absolute; left: 0; top: 0; }
</style>
<div class="layerBox">
<canvas id="layer1" width="300" height="300"></canvas>
<canvas id="layer2" width="300" height="300"></canvas>
</div>
<script>
const SIZE = 300;
const RADIUS = SIZE / 2 * 0.9;
var layer1 = document.getElementById("layer1");
var ctx1 = layer1.getContext("2d");
ctx1.translate(SIZE / 2, SIZE / 2);
drawFace(ctx1);
drawNumbers(ctx1);
var layer2 = document.getElementById("layer2");
var ctx2 = layer2.getContext("2d");
ctx2.translate(SIZE / 2, SIZE / 2);
drawTime(ctx2);
setInterval(() => {
ctx2.clearRect(-SIZE / 2, -SIZE / 2, SIZE, SIZE);
drawTime(ctx2);
} , 1000);
function drawFace(ctx) {
var grad = ctx.createRadialGradient(0, 0, RADIUS * 0.95, 0, 0, RADIUS * 1.05);
grad.addColorStop(0, "#333");
grad.addColorStop(0.5, "white");
grad.addColorStop(1, "#333");
ctx.beginPath();
ctx.arc(0, 0, RADIUS * 1.05, 0, Math.PI * 2);
ctx.fillStyle = grad;
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, RADIUS * 0.95, 0, Math.PI * 2);
ctx.fillStyle = "white";
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, RADIUS * 0.1, 0, Math.PI * 2);
ctx.fillStyle = "#333";
ctx.fill();
}
function drawNumbers(ctx) {
ctx.font = RADIUS * 0.2 + "px arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillStyle = "#333";
for (var num = 1; num <= 12; num++) {
var ang = num * Math.PI / 6;
ctx.save();
ctx.rotate(ang);
ctx.translate(0, -RADIUS * 0.82);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.restore();
}
}
function drawTime(ctx) {
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
// hour
hour = hour % 12;
var ang = (hour * (Math.PI / 6)) + (minute * (Math.PI / 6 / 60));
drawHand(ctx, ang, RADIUS * 0.5, RADIUS * 0.07);
// minute
ang = (minute * (Math.PI / 30)) + (second * (Math.PI / 30 / 60));
drawHand(ctx, ang, RADIUS * 0.8, RADIUS * 0.07);
// second
ang = second * (Math.PI / 30);
drawHand(ctx, ang, RADIUS * 0.9, RADIUS * 0.02);
}
function drawHand(ctx, ang, length, width) {
ctx.save();
ctx.lineCap = "round";
ctx.lineWidth = width;
ctx.strokeStyle = "#333";
ctx.rotate(ang);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, -length);
ctx.stroke();
ctx.restore();
}
</script>