Timelines - Canvas (CSS Transforms)

by justjohn

HTML

<div class="body">
    <div id="timelines" class="timelines"></div>
    <div id="timelinesOverlay" class="timelines_overlay"></div>
    <div class="stats">
        Time: <span class="time"></span>
        Offset: <span class="offset"></span>
        Time Offset: <span class="time_offset"></span>
        <!-- Wheel: <span class="wheel"></span> -->
    </div>
</div>

CSS

body {
    background:#555;
    margin:0;
    padding:0;
}
.body {
    position: absolute;
    left: 0px;
    right: 0px;
    top: 0px;
    bottom: 0px;
    
    background-color: #ccc; /* fallback color if gradients are not supported */

    background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#888)); 
    background-image: -webkit-linear-gradient(top, #eee, #888); 
    background-image:    -moz-linear-gradient(top, #eee, #888); 
    background-image:     -ms-linear-gradient(top, #eee, #888); 
    background-image:      -o-linear-gradient(top, #eee, #888); 
    background-image:         linear-gradient(to bottom, #eee, #888);
}
.timelines, .timelines_overlay {
    position: absolute;
    left: 20px;
    right: 20px;
    top: 20px;
    bottom: 40px;
    border: 1px solid #111;
}
.timelines {
    background-color: #333; /* fallback color if gradients are not supported */

    background-image: -webkit-gradient(linear, left top, left bottom, from(#444), to(#222)); 
    background-image: -webkit-linear-gradient(top, #444, #222); 
    background-image:    -moz-linear-gradient(top, #444, #222); 
    background-image:     -ms-linear-gradient(top, #444, #222); 
    background-image:      -o-linear-gradient(top, #444, #222); 
    background-image:         linear-gradient(to bottom, #444, #222);
    
}
.timelines_overlay {
     -moz-box-shadow: inset 0 .5em 2em #222;
  -webkit-box-shadow: inset 0 .5em 2em #222;
          box-shadow: inset 0 .5em 2em #222;
}
.timeline_container {
    position: absolute;
    overflow: hidden;
    height: 100%;
    left: 0;
    top: 0;
}
.timeline_container .timeline {
    position: absolute;
    left: 2px;
    right: 0;
    top: 0;
    bottom: 0;
    border-left: 1px solid #AAA;
}
.timeline_border {
    border-left: 1px solid #AAA;
    position: absolute;
    left: 1px;
    right: 0;
    top: 0;
    bottom: 0;
}

.timeline_container .timeline canvas {
    position:absolute;
    bottom:0;
}

.block {
   ...

JavaScript

var Canvas = {
    clear: function(canvas) {
        var ctx = canvas.getContext("2d");
         // Store the current transformation matrix
        ctx.save();
        
        // Use the identity matrix while clearing the canvas
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // Restore the transform
        ctx.restore();   
    }
};

var Block = function(params) {
    var start     = params.start,
        end       = params.end,
        toPixel   = params.toPixel,
        content   = params.content,
        container = params.container;
    
    this.panel = $('<div class="block" />');
    
    this.panel.css("top", toPixel(start));
    this.panel.css("height", toPixel(end - start));
};
Block.prototype = Block;

Block.draw = function() { };

var Timeline = function(params) {
    var parent    = $(params.container)
      , container = $('<div class="timeline_container"></div>')
      , timeline  = $('<div class="timeline"></div>')
      , canvas    = $('<canvas class="tick_canvas"></canvas>')
      , time      = $('<canvas class="timebar_canvas"></canvas>');
    
    timeline.append(canvas);
    container.append(timeline);
    parent.append(container);
    
    timeline.wrap('<div class="timeline_border" />');
    
    this.canvas    = canvas;
    this.container = container;
    this.timeline  = timeline;
    this.parent    = parent;
    
    this.time = {}; // Time distances relative to minutes
    this.time.minute = 20; 
    this.time.second = this.time.minute / 60; 
    this.time.hour   = this.time.minute * 60;
    this.time.day    = this.time.hour   * 24;
    
    // The time reference point (now), relative to the bottom of the timeline
    //   All times should be computed relative to this point.
    this.timeReference = new Date();
    
    // Time offset (from bottom) of the time reference
    this.offset = 0;
    
    // NOW is 5 minutes from the bottom.
    this.nowOffset =...