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

Seattle Weather

View full screen.

The New York Times regularly publishes compelling information displays online and in print. Even their weekly weather forecast is rich with information, showing the range of record, normal, actual and forecast temperatures (along with error bars!) for each day. Here we recreate the display for a recent week in Seattle.

Next: Oakland Crimespotting

Source

<html>
  <head>
    <title>Weather</title>
    <link type="text/css" rel="stylesheet" href="ex.css?3.1"/>
    <script type="text/javascript" src="../protovis-r3.1.0.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 2009 Stanford Visualization Group