d3 line graph

1. based on a tutorial 2. multiple series with different colors 3.

by hrabinowitz

HTML

<div id='description'>
    <pre>
        1. based on a tutorial
        2. multiple series with different colors, each a subarray of data
        3. handles null data values and won't draw line to it.
        4. dots are same color as line. no max color dot.
        4. don't show dots for null data values
        4. helpful stackoverflow on multiple series using svg:g.  http://stackoverflow.com/questions/11672438/can-d3-js-draw-two-scatterplots-on-the-same-graph-using-data-from-the-same-sourc
        5. use a scale and color pallette from d3
        TODO:
        1. (interactive) key
        2. title
        3. tooltips on points
    </pre>
</div>
<div id='chart' />

CSS

/*------------------------------------------------------------------------------------
  @group data
------------------------------------------------------------------------------------*/

text {
  fill: #ccc;
}

path {
  stroke-width: 1px;
  /*stroke: rgb(200,0,0);*/
  fill: none;
}

.tickx line,
.ticky line {
  stroke-width: 1px;
  stroke: #333;
  stroke-opacity: 0.4;
  shape-rendering: crispedges;
}

.tickx text,
.ticky text {
  fill: #444;
  font-size: 10px;
}

.point {
  /*fill: rgb(200,0,0);*/
  stroke-width: 2px;
  stroke: rgb(255,255,255);
}

.point.max {
  /*fill: rgb(51, 156, 255);*/
  fill: red;
  /*stroke-width: 2px;*/
  stroke-width: 2px;
}

JavaScript

"use strict";
    var data, h, max, pb, pl, pr, pt, ticks, version, vis, w, x, y, _ref;
    version = Number(document.location.hash.replace('#', ''));
    // TODO: does not handle nulls right for line segments
    var data = [[3, 7, 95, 25, 4, 6, 8, 2, 55],
            [3, 7, 81, null, 39, 29, 8, 2, 55],
            [3, 7, 15, null, 17, 77, 8, 2, 55],
            [3, 7, 24, 70, null, 41, 78, 20, 55]
           ];
    var pad_ref = [20, 20, 20, 20];
    // paddings
    var pt = pad_ref[0]; // padding top
    var pl = pad_ref[1]; 
    var pr = pad_ref[2]; 
    var pb = pad_ref[3];

    var w = 800 - (pl + pr);
    var h = 300 - (pt + pb);
    // TODO: the max needs fixing so it is max over all series
    var max = d3.max(data[0]);

    var xscale = d3.scale.linear().domain([0, data[0].length - 1]).range([0, w]);
    var yscale = d3.scale.linear().domain([0, max]).range([h, 0]);
    
    vis = d3.select('#chart').
        style('margin', '20px auto').
        style('width', "" + w + "px").
        append('svg:svg').
        attr('width', w + (pl + pr)).
        attr('height', h + pt + pb).
        attr('class', 'viz').
        append('svg:g').
        attr('transform', "translate(" + pl + "," + pt + ")");

    var lines = vis.selectAll('path.line').
        data(data).
        enter().
        append("svg:path").
        attr("d", d3.svg.line().
                     // this defined() method handles undefined points
                     defined(function(d) {
                         return (d != null);
                     }).
                     x(function(d, i) {
                          return xscale(i);
                     }).
                     y(function(d, i) {
                         return yscale(d);
                     })
            );

    var colorScale = d3.scale.category20();

    lines.attr("stroke", function(d, i) {
        //return ["red", "green", "blue"][i];
        return colorScale(i);
    });

    if (version < 2 && version !== 0) {
    ...