Clock2

by uedatakuya

HTML

<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    <circle id="clockBody" data-bind="attr:{cx:body.cx, cy:body.cy, r:body.r}"/>
    <line id="hour"  data-bind="attr:{transform: hour.transform, x1:hour.x1, y1:hour.y1, x2:hour.x2, y2:hour.y2}" />
    <line id="minute"  data-bind="attr:{transform: minute.transform, x1:minute.x1, y1:minute.y1, x2:minute.x2, y2:minute.y2}" />
    <line id="second"  data-bind="attr:{transform: second.transform, x1:second.x1, y1:second.y1, x2:second.x2, y2:second.y2}" />
</svg>

CSS

#clockBody {fill:seashell; stroke:black; stroke-width:1;}
line {stroke:black;}    
#hour {stroke-width:3;}
#minute {stroke-width:2;}
#second {stroke:red;stroke-width:1;}

CoffeeScript

class Rotate                        
    constructor:(param)->
        @angle = param.angle ? ko.observable(0)
        @x = param.x ? ko.observable(0)
        @y = param.y ? ko.observable(0)
    toString:->
        "rotate(#{@angle()},#{@x()},#{@y()})"
        
class Shape
    constructor:->
        @transformArray = ko.observableArray()
        @transform = ko.computed(()=>
            (t.toString() for t in @transformArray()).join(" ")
        , @)

class Line extends Shape
    constructor:(param)->
        super()
        @x1 = param.x1 ? ko.observable(0)
        @y1 = param.y1 ? ko.observable(0)
        @x2 = param.x2 ? ko.observable(0)
        @y2 = param.y2 ? ko.observable(0)
        @transformArray.push(param.transforms) if param.transforms

class Circle extends Shape
    constructor:(param) ->
        super()
        @cx = param.cx ? ko.observable(0)
        @cy = param.cy ? ko.observable(0)
        @r  = param.r ? ko.observable(1)
        @transformArray.push(param.transforms) if param.transforms

class Clock

    constructor:->
        @date = ko.observable(new Date())

        @body = new Circle(
            cx: ko.observable(100)
            cy: ko.observable(100)
            r: ko.observable(100)
        )

        @hour = new Line(
            x1: @body.cx
            y1: @body.cy
            x2: @body.cx
            y2:
                ko.computed(()=>                    
                    if @body?
                        @body.cy() - @body.r() * 0.5
                    else
                        0
                , @)
            transforms:
                new Rotate(                    
                    angle:
                        ko.computed(()=>
                            (@date().getHours() % 12) / 12 * 360
                        , @)
                    x: @body.cx
                    y: @body.cy
                )                    
        )

        @minute = new Line(
            x1: @body.cx
            y1: @body.cy
       ...