Skip to content

Instantly share code, notes, and snippets.

@bewest
Forked from mbostock/.block
Created December 17, 2012 08:38

Revisions

  1. @mbostock mbostock revised this gist Oct 12, 2012. 1 changed file with 0 additions and 0 deletions.
    Binary file added thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  2. @mbostock mbostock revised this gist Jun 28, 2012. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,3 @@
    An example of the [d3.horizon](https://github.com/d3/d3-plugins/tree/master/horizon) plugin.
    Horizon charts combine position and color to reduce vertical space. Start with a standard area chart, then **mirror** negative values (in blue) or **offset** them vertically. Click the **+ button** above to increase the number of bands, turning the area into a horizon.

    Implemented with the [d3.horizon](https://github.com/d3/d3-plugins/tree/master/horizon) plugin.
  3. @mbostock mbostock revised this gist Jun 28, 2012. 1 changed file with 4 additions and 6 deletions.
    10 changes: 4 additions & 6 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    <style>

    body {
    font: 10px sans-serif;
    font-family: sans-serif;
    }

    svg {
    @@ -11,15 +11,13 @@

    #horizon-controls {
    position: absolute;
    width: 960px;
    font-size: 16px;
    margin-bottom: 6px;
    width: 940px;
    padding: 10px;
    z-index: 1;
    }

    #horizon-bands {
    position: absolute;
    right: 0;
    float: right;
    }

    </style>
  4. @mbostock mbostock revised this gist Jun 28, 2012. 1 changed file with 14 additions and 4 deletions.
    18 changes: 14 additions & 4 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,20 @@
    <style>

    body {
    font: 10px sans-serif;
    }

    svg {
    position: absolute;
    top: 0;
    }

    #horizon-controls {
    position: relative;
    width: 100%;
    position: absolute;
    width: 960px;
    font-size: 16px;
    margin-bottom: 6px;
    z-index: 1;
    }

    #horizon-bands {
    @@ -19,12 +29,12 @@
    <span id="horizon-bands"><span id="horizon-bands-value">1</span> <button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>
    <div id="horizon-chart"></div>
    <script src="http://d3js.org/d3.v2.min.js?2.9.5"></script>
    <script src="http://d3js.org/d3.v2.js?2.9.5"></script>
    <script src="horizon.js?0.0.1"></script>
    <script>

    var width = 960,
    height = 360;
    height = 500;

    var chart = d3.horizon()
    .width(width)
  5. @mbostock mbostock revised this gist Jun 28, 2012. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -19,6 +19,7 @@
    <span id="horizon-bands"><span id="horizon-bands-value">1</span> <button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>
    <div id="horizon-chart"></div>
    <script src="http://d3js.org/d3.v2.min.js?2.9.5"></script>
    <script src="horizon.js?0.0.1"></script>
    <script>

  6. @mbostock mbostock revised this gist Jun 28, 2012. 3 changed files with 231 additions and 41 deletions.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    Note: this uses the d3.chart module, which is deprecated. I need to rewrite the horizon component!
    An example of the [d3.horizon](https://github.com/d3/d3-plugins/tree/master/horizon) plugin.
    192 changes: 192 additions & 0 deletions horizon.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,192 @@
    (function() {
    d3.horizon = function() {
    var bands = 1, // between 1 and 5, typically
    mode = "offset", // or mirror
    interpolate = "linear", // or basis, monotone, step-before, etc.
    x = d3_horizonX,
    y = d3_horizonY,
    w = 960,
    h = 40,
    duration = 0;

    var color = d3.scale.linear()
    .domain([-1, 0, 0, 1])
    .range(["#08519c", "#bdd7e7", "#bae4b3", "#006d2c"]);

    // For each small multiple…
    function horizon(g) {
    g.each(function(d, i) {
    var g = d3.select(this),
    n = 2 * bands + 1,
    xMin = Infinity,
    xMax = -Infinity,
    yMax = -Infinity,
    x0, // old x-scale
    y0, // old y-scale
    id; // unique id for paths

    // Compute x- and y-values along with extents.
    var data = d.map(function(d, i) {
    var xv = x.call(this, d, i),
    yv = y.call(this, d, i);
    if (xv < xMin) xMin = xv;
    if (xv > xMax) xMax = xv;
    if (-yv > yMax) yMax = -yv;
    if (yv > yMax) yMax = yv;
    return [xv, yv];
    });

    // Compute the new x- and y-scales, and transform.
    var x1 = d3.scale.linear().domain([xMin, xMax]).range([0, w]),
    y1 = d3.scale.linear().domain([0, yMax]).range([0, h * bands]),
    t1 = d3_horizonTransform(bands, h, mode);

    // Retrieve the old scales, if this is an update.
    if (this.__chart__) {
    x0 = this.__chart__.x;
    y0 = this.__chart__.y;
    t0 = this.__chart__.t;
    id = this.__chart__.id;
    } else {
    x0 = x1.copy();
    y0 = y1.copy();
    t0 = t1;
    id = ++d3_horizonId;
    }

    // We'll use a defs to store the area path and the clip path.
    var defs = g.selectAll("defs")
    .data([null]);

    // The clip path is a simple rect.
    defs.enter().append("defs").append("clipPath")
    .attr("id", "d3_horizon_clip" + id)
    .append("rect")
    .attr("width", w)
    .attr("height", h);

    defs.select("rect").transition()
    .duration(duration)
    .attr("width", w)
    .attr("height", h);

    // We'll use a container to clip all horizon layers at once.
    g.selectAll("g")
    .data([null])
    .enter().append("g")
    .attr("clip-path", "url(#d3_horizon_clip" + id + ")");

    // Instantiate each copy of the path with different transforms.
    var path = g.select("g").selectAll("path")
    .data(d3.range(-1, -bands - 1, -1).concat(d3.range(1, bands + 1)), Number);

    var d0 = d3_horizonArea
    .interpolate(interpolate)
    .x(function(d) { return x0(d[0]); })
    .y0(h * bands)
    .y1(function(d) { return h * bands - y0(d[1]); })
    (data);

    var d1 = d3_horizonArea
    .x(function(d) { return x1(d[0]); })
    .y1(function(d) { return h * bands - y1(d[1]); })
    (data);

    path.enter().append("path")
    .style("fill", color)
    .attr("transform", t0)
    .attr("d", d0);

    path.transition()
    .duration(duration)
    .style("fill", color)
    .attr("transform", t1)
    .attr("d", d1);

    path.exit().transition()
    .duration(duration)
    .attr("transform", t1)
    .attr("d", d1)
    .remove();

    // Stash the new scales.
    this.__chart__ = {x: x1, y: y1, t: t1, id: id};
    });
    d3.timer.flush();
    }

    horizon.duration = function(x) {
    if (!arguments.length) return duration;
    duration = +x;
    return horizon;
    };

    horizon.bands = function(x) {
    if (!arguments.length) return bands;
    bands = +x;
    color.domain([-bands, 0, 0, bands]);
    return horizon;
    };

    horizon.mode = function(x) {
    if (!arguments.length) return mode;
    mode = x + "";
    return horizon;
    };

    horizon.colors = function(x) {
    if (!arguments.length) return color.range();
    color.range(x);
    return horizon;
    };

    horizon.interpolate = function(x) {
    if (!arguments.length) return interpolate;
    interpolate = x + "";
    return horizon;
    };

    horizon.x = function(z) {
    if (!arguments.length) return x;
    x = z;
    return horizon;
    };

    horizon.y = function(z) {
    if (!arguments.length) return y;
    y = z;
    return horizon;
    };

    horizon.width = function(x) {
    if (!arguments.length) return w;
    w = +x;
    return horizon;
    };

    horizon.height = function(x) {
    if (!arguments.length) return h;
    h = +x;
    return horizon;
    };

    return horizon;
    };

    var d3_horizonArea = d3.svg.area(),
    d3_horizonId = 0;

    function d3_horizonX(d) {
    return d[0];
    }

    function d3_horizonY(d) {
    return d[1];
    }

    function d3_horizonTransform(bands, h, mode) {
    return mode == "offset"
    ? function(d) { return "translate(0," + (d + (d < 0) - bands) * h + ")"; }
    : function(d) { return (d < 0 ? "scale(1,-1)" : "") + "translate(0," + (d - bands) * h + ")"; };
    }
    })();
    78 changes: 38 additions & 40 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,31 +1,40 @@
    <!DOCTYPE html>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <style>

    <div id="chart"></div>

    <div id="controls">
    <input name="mode" type="radio" value="offset" id="mode-offset" checked><label for="mode-offset"> Offset</label>
    <input name="mode" type="radio" value="mirror" id="mode-mirror"><label for="mode-mirror"> Mirror</label>
    <span id="bands"><button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>

    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.7.0"></script>
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.chart.js?2.7.0"></script>
    <script type="text/javascript">
    #horizon-controls {
    position: relative;
    width: 100%;
    font-size: 16px;
    margin-bottom: 6px;
    }

    var w = 960,
    h = 80;
    #horizon-bands {
    position: absolute;
    right: 0;
    }

    var chart = d3.chart.horizon()
    .width(w)
    .height(h)
    .bands(5)
    .mode("offset")
    </style>
    <div id="horizon-controls">
    <input name="mode" type="radio" value="mirror" id="horizon-mode-mirror" checked><label for="horizon-mode-mirror"> Mirror</label>
    <input name="mode" type="radio" value="offset" id="horizon-mode-offset"><label for="horizon-mode-offset"> Offset</label>
    <span id="horizon-bands"><span id="horizon-bands-value">1</span> <button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>
    <div id="horizon-chart"></div>
    <script src="horizon.js?0.0.1"></script>
    <script>

    var width = 960,
    height = 360;

    var chart = d3.horizon()
    .width(width)
    .height(height)
    .bands(1)
    .mode("mirror")
    .interpolate("basis");

    var svg = d3.select("#chart").append("svg")
    .attr("width", w)
    .attr("height", h);
    var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

    d3.json("unemployment.json", function(data) {

    @@ -41,27 +50,16 @@
    svg.data([data]).call(chart);

    // Enable mode buttons.
    d3.selectAll("input[name=mode]").on("change", function() {
    d3.selectAll("#horizon-controls input[name=mode]").on("change", function() {
    svg.call(chart.duration(0).mode(this.value));
    });

    // Enable bands buttons.
    d3.selectAll("#bands button").data([-1, 1]).on("click", function(d) {
    svg.call(chart.duration(1000).bands(Math.max(1, chart.bands() + d)));
    d3.selectAll("#horizon-bands button").data([-1, 1]).on("click", function(d) {
    var n = Math.max(1, chart.bands() + d);
    d3.select("#horizon-bands-value").text(n);
    svg.call(chart.duration(1000).bands(n).height(height / n));
    });
    });

    </script>
    <style type="text/css">

    #controls {
    position: relative;
    width: 960px;
    }

    #bands {
    position: absolute;
    right: 0;
    }

    </style>
    </script>
  7. @mbostock mbostock revised this gist Dec 15, 2011. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -4,8 +4,8 @@
    <div id="chart"></div>

    <div id="controls">
    <input name="mode" type="radio" id="offset" checked><label for="offset"> Offset</label>
    <input name="mode" type="radio" id="mirror"><label for="mirror"> Mirror</label>
    <input name="mode" type="radio" value="offset" id="mode-offset" checked><label for="mode-offset"> Offset</label>
    <input name="mode" type="radio" value="mirror" id="mode-mirror"><label for="mode-mirror"> Mirror</label>
    <span id="bands"><button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>

  8. @mbostock mbostock revised this gist Dec 15, 2011. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -4,8 +4,8 @@
    <div id="chart"></div>

    <div id="controls">
    <input name="mode" id="offset" checked><label for="offset"> Offset</label>
    <input name="mode" id="mirror"><label for="mirror"> Mirror</label>
    <input name="mode" type="radio" id="offset" checked><label for="offset"> Offset</label>
    <input name="mode" type="radio" id="mirror"><label for="mirror"> Mirror</label>
    <span id="bands"><button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>

    @@ -14,7 +14,7 @@
    <script type="text/javascript">

    var w = 960,
    h = 120;
    h = 80;

    var chart = d3.chart.horizon()
    .width(w)
  9. @mbostock mbostock revised this gist Dec 15, 2011. 1 changed file with 9 additions and 24 deletions.
    33 changes: 9 additions & 24 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -4,14 +4,9 @@
    <div id="chart"></div>

    <div id="controls">
    <span id="mode">
    <button class="first active">Offset</button
    ><button class="last">Mirror</button>
    </span>
    <span id="bands">
    <button class="first">&#x2212;</button
    ><button class="last">+</button>
    </span>
    <input name="mode" id="offset" checked><label for="offset"> Offset</label>
    <input name="mode" id="mirror"><label for="mirror"> Mirror</label>
    <span id="bands"><button class="first">&#x2212;</button><button class="last">+</button></span>
    </div>

    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.7.0"></script>
    @@ -46,29 +41,19 @@
    svg.data([data]).call(chart);

    // Enable mode buttons.
    d3.selectAll("#mode button")
    .data(["offset", "mirror"])
    .on("click", function(m) {
    svg.call(chart.duration(0).mode(m));
    d3.selectAll("#mode button")
    .classed("active", function(d) { return d == m; });
    });
    d3.selectAll("input[name=mode]").on("change", function() {
    svg.call(chart.duration(0).mode(this.value));
    });

    // Enable bands buttons.
    d3.selectAll("#bands button")
    .data([-1, 1])
    .on("click", function bands(db) {
    svg.call(chart.duration(1000).bands(Math.max(1, chart.bands() + db)));
    });
    d3.selectAll("#bands button").data([-1, 1]).on("click", function(d) {
    svg.call(chart.duration(1000).bands(Math.max(1, chart.bands() + d)));
    });
    });

    </script>
    <style type="text/css">

    button.active {
    background-color: rgb(65,102,133);
    }

    #controls {
    position: relative;
    width: 960px;
  10. @mbostock mbostock revised this gist Dec 15, 2011. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -65,6 +65,10 @@
    </script>
    <style type="text/css">

    button.active {
    background-color: rgb(65,102,133);
    }

    #controls {
    position: relative;
    width: 960px;
  11. @mbostock mbostock revised this gist Dec 15, 2011. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@
    <script type="text/javascript">

    var w = 960,
    h = 40;
    h = 120;

    var chart = d3.chart.horizon()
    .width(w)
  12. @mbostock mbostock created this gist Dec 15, 2011.
    1 change: 1 addition & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    Note: this uses the d3.chart module, which is deprecated. I need to rewrite the horizon component!
    78 changes: 78 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    <!DOCTYPE html>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">

    <div id="chart"></div>

    <div id="controls">
    <span id="mode">
    <button class="first active">Offset</button
    ><button class="last">Mirror</button>
    </span>
    <span id="bands">
    <button class="first">&#x2212;</button
    ><button class="last">+</button>
    </span>
    </div>

    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.7.0"></script>
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.chart.js?2.7.0"></script>
    <script type="text/javascript">

    var w = 960,
    h = 40;

    var chart = d3.chart.horizon()
    .width(w)
    .height(h)
    .bands(5)
    .mode("offset")
    .interpolate("basis");

    var svg = d3.select("#chart").append("svg")
    .attr("width", w)
    .attr("height", h);

    d3.json("unemployment.json", function(data) {

    // Offset so that positive is above-average and negative is below-average.
    var mean = data.rate.reduce(function(p, v) { return p + v; }, 0) / data.rate.length;

    // Transpose column values to rows.
    data = data.rate.map(function(rate, i) {
    return [Date.UTC(data.year[i], data.month[i] - 1), rate - mean];
    });

    // Render the chart.
    svg.data([data]).call(chart);

    // Enable mode buttons.
    d3.selectAll("#mode button")
    .data(["offset", "mirror"])
    .on("click", function(m) {
    svg.call(chart.duration(0).mode(m));
    d3.selectAll("#mode button")
    .classed("active", function(d) { return d == m; });
    });

    // Enable bands buttons.
    d3.selectAll("#bands button")
    .data([-1, 1])
    .on("click", function bands(db) {
    svg.call(chart.duration(1000).bands(Math.max(1, chart.bands() + db)));
    });
    });

    </script>
    <style type="text/css">

    #controls {
    position: relative;
    width: 960px;
    }

    #bands {
    position: absolute;
    right: 0;
    }

    </style>
    1 change: 1 addition & 0 deletions unemployment.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    {"year":[2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2001,2001,2001,2001,2001,2001,2001,2001,2001,2001,2001,2001,2002,2002,2002,2002,2002,2002,2002,2002,2002,2002,2002,2002,2003,2003,2003,2003,2003,2003,2003,2003,2003,2003,2003,2003,2004,2004,2004,2004,2004,2004,2004,2004,2004,2004,2004,2004,2005,2005,2005,2005,2005,2005,2005,2005,2005,2005,2005,2005,2006,2006,2006,2006,2006,2006,2006,2006,2006,2006,2006,2006,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2010,2010],"month":[1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2],"rate":[4.5,4.4,4.3,3.7,3.8,4.1,4.2,4.1,3.8,3.6,3.7,3.7,4.7,4.6,4.5,4.2,4.1,4.7,4.7,4.9,4.7,5,5.3,5.4,6.3,6.1,6.1,5.7,5.5,6,5.9,5.7,5.4,5.3,5.6,5.7,6.5,6.4,6.2,5.8,5.8,6.5,6.3,6,5.8,5.6,5.6,5.4,6.3,6,6,5.4,5.3,5.8,5.7,5.4,5.1,5.1,5.2,5.1,5.7,5.8,5.4,4.9,4.9,5.2,5.2,4.9,4.8,4.6,4.8,4.6,5.1,5.1,4.8,4.5,4.4,4.8,5,4.6,4.4,4.1,4.3,4.3,5,4.9,4.5,4.3,4.3,4.7,4.9,4.6,4.5,4.4,4.5,4.8,5.4,5.2,5.2,4.8,5.2,5.7,6,6.1,6,6.1,6.5,7.1,8.5,8.9,9,8.6,9.1,9.7,9.7,9.6,9.5,9.5,9.4,9.7,10.6,10.4]}