Horizon Graph Example

By dividing an area chart into consecutive layers, horizon graphs present time-series data in a compact space while preserving resolution. Click the chart to change the number of layers. Though the chart size changes, the spatial resolution of the area chart stays constant.

Vega JSON Specification <>

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A horizon graph, which preserves resolution by layering slices of an area chart.",
  "width": 500,
  "height": 100,

  "signals": [
    {
      "name": "layers",
      "value": 2,
      "on": [{"events": "pointerdown!", "update": "1 + (layers % 4)"}],
      "bind": {"input": "select", "options": [1, 2, 3, 4]}
    },
    {
      "name": "height",
      "update": "floor(200 / layers)"
    },
    {
      "name": "vheight",
      "update": "height * layers"
    },
    {
      "name": "opacity",
      "update": "pow(layers, -2/3)"
    }
  ],

  "data": [
    {
      "name": "layer_indices",
      "values": [0, 1, 2, 3],
      "transform": [
        {"type": "filter", "expr": "datum.data < layers"},
        {"type": "formula", "expr": "datum.data * -height", "as": "offset"}
      ]
    },
    {
      "name": "table",
      "values": [
        {"x": 1,  "y": 28}, {"x": 2,  "y": 55},
        {"x": 3,  "y": 43}, {"x": 4,  "y": 91},
        {"x": 5,  "y": 81}, {"x": 6,  "y": 53},
        {"x": 7,  "y": 19}, {"x": 8,  "y": 87},
        {"x": 9,  "y": 52}, {"x": 10, "y": 48},
        {"x": 11, "y": 24}, {"x": 12, "y": 49},
        {"x": 13, "y": 87}, {"x": 14, "y": 66},
        {"x": 15, "y": 17}, {"x": 16, "y": 27},
        {"x": 17, "y": 68}, {"x": 18, "y": 16},
        {"x": 19, "y": 49}, {"x": 20, "y": 15}
      ]
    }
  ],

  "scales": [
    {
      "name": "x",
      "type": "linear",
      "range": "width",
      "zero": false, "round": true,
      "domain": {"data": "table", "field": "x"}
    },
    {
      "name": "y",
      "type": "linear",
      "range": [{"signal":"vheight"}, 0],
      "nice": true, "zero": true,
      "domain": {"data": "table", "field": "y"}
    }
  ],

  "axes": [
    {"orient": "bottom", "scale": "x", "tickCount": 20}
  ],

  "marks": [
    {
      "type": "group",
      "encode": {
        "update": {
          "width": {"field": {"group": "width"}},
          "height": {"field": {"group": "height"}},
          "clip": {"value": true}
        }
      },
      "marks": [
        {
          "type": "group",
          "from": {"data": "layer_indices"},
          "encode": {
            "update": {
              "y": {"field": "offset"}
            }
          },
          "marks": [
            {
              "type": "area",
              "from": {"data": "table"},
              "encode": {
                "enter": {
                  "interpolate": {"value": "monotone"},
                  "x": {"scale": "x", "field": "x"},
                  "fill": {"value": "steelblue"}
                },
                "update": {
                  "y": {"scale": "y", "field": "y"},
                  "y2": {"scale": "y", "value": 0},
                  "fillOpacity": {"signal": "opacity"}
                }
              }
            }
          ]
        }
      ]
    }
  ]
}