2014年12月3日水曜日

Lesson16: Canvas (時計)

このサイトは移転しました。1秒後に自動でジャンプします。
移動しない場合は、ここをクリックしてください。



今年も残りあと1ヶ月。
新しいことをはじめようと意気込んだこの一年、結局、例年とあまり変わらない一年で終わりそうなので、来年につなげられるよう、しばらく中断していた記事を日々書いていこうと思います。

『息子に教えるJavaScript』と銘打って書き始めたものの、教えたいことがたくさんありすぎて、思いばかりが先に行ってしまっています。
コンピュータ、算数、科学・・・。少なくとも、自分が学んできたことの多くを息子に教えたい。本当に学ぶべきことは、もっと先にあるのだから、基礎となる部分だけでも教えられればと思います。

本Blogは、プログラミングを通して息子にコンピュータを教えたいという思いで書きはじめました。コンピュータの使い方は様々ですが、仕組みを理解するという点でプログラミングを学んでほしいと考え、身近なブラウザ上で動かせるJavaScriptを教えることにしました。

今回は、Canvasを使ったサンプルはないかと部屋を見渡したところ、たまたま時計が目に入ったので、アナログ時計を表示してみたいと思います。

あまり綺麗なソースではありませんが、細かいことは気にせずに、習うより慣れろ式に、短めのサンプルを例に挙げて、教えるきっかけになればと考えています。

https://github.com/toshio/js4son/blob/master/chapter02/lesson16.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Lesson16 Clock</title>
    <style>
    html, body {
        width:    100%;
        height:   100%;
        margin:   0;
        padding:  0;
        overflow: hidden;
    }
    canvas {
        position: absolute;
    }
    </style>
  </head>
  <body>
    <canvas id="myCanvas"></canvas>

    <script>
    function drawClock() {
        var canvas  = document.getElementById("myCanvas");
        var context = canvas.getContext("2d");
        var width   = canvas.width;
        var height  = canvas.height;
        var radius  = Math.min(width, height) / 2.0 * 0.8;
        var cx      = width  / 2;
        var cy      = height / 2;

        // Time
        var date   = new Date();
        var hour   = date.getHours() % 12;
        var minute = date.getMinutes();
        var second = date.getSeconds();

        // Clear canvas
        context.beginPath();
        context.fillStyle = "white";
        context.fillRect(0, 0, width, height);

        // Circle
        context.beginPath();
        context.arc(cx, cy, radius, 0, Math.PI * 2, true);
        context.strokeStyle = "black";
        context.lineWidth   = 5;
        context.stroke();

        // Numbers
        var hours = ["Ⅻ","Ⅰ","Ⅱ","Ⅲ","Ⅳ","Ⅴ","Ⅵ","Ⅶ","Ⅷ","Ⅸ","Ⅹ","Ⅺ"];
        context.beginPath();
        context.textAlign    = "center";
        context.textBaseline = "middle";
        context.font         = Math.floor(radius * 0.15) + "px 'MS 明朝'";
        context.fillStyle    = "black";
        for (var index in hours) {
            var radiusNumber = radius * 0.85;
            var thetaNumber  = (2 * Math.PI / 12 ) * index;
            var posNumber    = calcPosition(cx, cy, radiusNumber, thetaNumber);
            context.fillText(hours[index], posNumber.x, posNumber.y);
        }

        // Hour hand
        var radiusHour = radius * 0.7;
        var thetaHour  = (2 * Math.PI / 12 ) * (hour + minute / 60 + second / 3600);
        var posHour    = calcPosition(cx, cy, radiusHour, thetaHour);
        context.beginPath();
        context.moveTo(cx,  cy);
        context.lineTo(posHour.x, posHour.y);
        context.lineWidth = 4;
        context.stroke();

        // Minute hand
        var radiusMinute = radius * 0.9;
        var thetaMinute  = (2 * Math.PI / 60) * (minute + second / 60);
        var posMinute    = calcPosition(cx, cy, radiusMinute, thetaMinute);
        context.beginPath();
        context.moveTo(cx,  cy);
        context.lineTo(posMinute.x, posMinute.y);
        context.lineWidth = 3;
        context.stroke();

        // Second hand
        var radiusSecond = radius * 0.9;
        var thetaSecond  = (2 * Math.PI / 60) * second;
        var posSecond    = calcPosition(cx, cy, radiusSecond, thetaSecond);
        context.beginPath();
        context.moveTo(cx,  cy);
        context.lineTo(posSecond.x, posSecond.y);
        context.strokeStyle = "red";
        context.lineWidth   = 1;
        context.stroke();

        // Invoke when second changed
        setTimeout(drawClock, 1000 - date.getMilliseconds());
    }

    function calcPosition(cx, cy, radius, theta) {
        return {
            x: cx + (radius * Math.sin(theta)),
            y: cy - (radius * Math.cos(theta))
        };
    }

    function resize() {
        var canvas = document.getElementById("myCanvas");
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        drawClock();
    }

    window.addEventListener("resize", resize, false);
    window.addEventListener("load",   resize, false);
    </script>
  </body>
</html>

0 件のコメント:

コメントを投稿