A graphical toolkit for visualization
Protovis
Overview
Examples
Documentation
Download
Index
« Previous / Next »

Seattle Weather

View full screen.

Another compelling information display from The New York Times, this weekly weather forecast is rich with information: it shows the range of record, normal, actual and forecast temperatures (along with error bars!) for each day. The design is similar to a candlestick chart. Here we recreate the display for a recent week in Seattle.
Next: Marey’s Trains

Source

<html>
  <head>
    <title>Weather</title>
    <link type="text/css" rel="stylesheet" href="ex.css?3.2"/>
    <script type="text/javascript" src="../protovis-r3.2.js"></script>
    <script type="text/javascript" src="weather.js"></script>
    <style type="text/css">
      #fig {
        width: 200px;
        height: 250px;
      }
    </style>
  </head>
  <body><div id="center"><div id="fig">
    <script type="text/javascript+protovis">

      var w = 18, h = 3;

      var vis = new pv.Panel()
          .width(200)
          .height(250);

      /* Record range. */
      var record = vis.add(pv.Bar)
          .data(weather)
          .bottom(function(d) d.record.low * h)
          .height(function(d) (d.record.high - d.record.low) * h)
          .left(function() this.index * w)
          .width(w - 2)
          .fillStyle("#ccc");

      /* Normal range. */
      record.add(pv.Bar)
          .bottom(function(d) d.normal.low * h)
          .height(function(d) (d.normal.high - d.normal.low) * h)
          .fillStyle("#999");

      /* White grid lines. */
      vis.add(pv.Rule)
          .data([20, 40, 60])
          .bottom(function(d) d * h + 1)
          .left(0).right(20)
          .lineWidth(2).strokeStyle("white")
        .anchor("right").add(pv.Label)
          .text(function(d) d + "\u00b0");

      /* Actual and forecast range. */
      record.add(pv.Bar)
          .visible(function(d) d.actual)
          .bottom(function(d) d.actual.low * h)
          .height(function(d) (d.actual.high - d.actual.low) * h)
          .left(function() this.index * w + 3)
          .width(w - 8)
          .fillStyle("black")
        .add(pv.Bar)
          .visible(function(d) d.forecast)
          .bottom(function(d) d.forecast.high.low * h)
          .height(function(d) (d.forecast.high.high - d.forecast.high.low) * h)
        .add(pv.Bar)
          .bottom(function(d) d.forecast.low.low * h)
          .height(function(d) (d.forecast.low.high - d.forecast.low.low) * h)
        .add(pv.Bar)
          .bottom(function(d) d.forecast.low.low * h)
          .height(function(d) (d.forecast.high.high - d.forecast.low.low) * h)
          .left(function() this.index * w + 3 + Math.floor((w - 8) / 3))
          .width(Math.ceil((w - 8) / 3));

      /* Day labels. */
      record.anchor("top").add(pv.Label)
          .top(16)
          .text(function(d) d.day);

      /* Title. */
      vis.add(pv.Label)
          .top(0).left(0)
          .textBaseline("top")
          .font("bold 10pt Sans-Serif")
          .text("Seattle ");

      vis.render();

    </script>
  </div></div></body>
</html>

Data

var weather = [
  { day: "M",
    record: { high: 62, low: 15 },
    normal: { high: 50, low: 38 },
    actual: { high: 48, low: 36 } },
  { day: "T",
    record: { high: 62, low: 23 },
    normal: { high: 50, low: 38 },
    actual: { high: 50, low: 40 } },
  { day: "W",
    record: { high: 61, low: 20 },
    normal: { high: 50, low: 38 },
    actual: { high: 55, low: 36 } },
  { day: "T",
    record: { high: 67, low: 21 },
    normal: { high: 50, low: 38 },
    actual: { high: 51, low: 33 } },
  { day: "F",
    record: { high: 61, low: 23 },
    normal: { high: 50, low: 38 },
    actual: { high: 50, low: 30 } },
  { day: "S",
    record: { high: 67, low: 20 },
    normal: { high: 50, low: 38 },
    forecast: { high: { high: 53, low: 49 }, low: { high: 40, low: 35 } } },
  { day: "S",
    record: { high: 63, low: 23 },
    normal: { high: 50, low: 39 },
    forecast: { high: { high: 55, low: 49 }, low: { high: 42, low: 37 } } },
  { day: "M",
    record: { high: 61, low: 26 },
    normal: { high: 51, low: 39 },
    forecast: { high: { high: 53, low: 49 }, low: { high: 43, low: 40 } } },
  { day: "T",
    record: { high: 61, low: 24 },
    normal: { high: 51, low: 39 },
    forecast: { high: { high: 52, low: 46 }, low: { high: 44, low: 40 } } },
  { day: "W",
    record: { high: 63, low: 20 },
    normal: { high: 51, low: 39 },
    forecast: { high: { high: 53, low: 46 }, low: { high: 43, low: 38 } } }
];
Copyright 2010 Stanford Visualization Group