Align bar chart with line chart (bands with linear scale)?

110 views
Skip to first unread message

Eric Socolofsky

unread,
Jan 24, 2018, 8:28:49 PM1/24/18
to vega-js
I'm attempting to create hit areas that trigger a vertical rule and a vega-tooltip that align with points on a line chart. This image shows where I'm at now, with extra padding on the band scale for clarity:



The line chart uses a `type: linear` scale; the rule and rects use a `type: band` scale. Is there any way to align the rule and rect centers with the points of the line scale? Alternatively, should I be using a different scale type to draw the rects/rule?

Here's my spec, trimmed down to just the relevant bits:

{
  "signals": [
    {
      "name": "tooltip",
      "value": {},
      "on": [
        {
          "events": "@tooltip-hitarea:mouseover",
          "update": "datum"
        },
        {
          "events": "@tooltip-hitarea:mouseout",
          "update": "{}"
        }
      ]
    }
  ],
  "scales": [
    {
      "name": "x_0_0",
      "type": "time",
      "domain": {
        "data": "output_0_0",
        "field": "x_out"
      },
      "zero": false,
      "range": "width"
    },
    {
      "name": "x_0_tooltip",
      "type": "band",
      "domain": {
        "data": "output_0_0",
        "field": "x_out"
      },
      "range": "width",
      "zero": false,
      "padding": 0.2,
      "round": true
    },
  ],
  "marks": [
    {
      "type": "line",
      "interactive": false,
      "encode": {
        "enter": {
          "x": {
            "scale": "x_0_0",
            "field": "x_out"
          }
        }
      }
    },
    {
      "type": "symbol",
      "interactive": false,
      "encode": {
        "update": {
          "x": {
            "scale": "x_0_0",
            "field": "x_out"
          }
        }
      }
    },
    {
      "type": "rule",
      "interactive": false,
      "encode": {
        "update": {
          "x": {
            "scale": "x_0_tooltip",
            "signal": "tooltip.x_out",
            "band": 0.5
          }
        }
      }
    },
    {
      "name": "tooltip-hitarea",
      "type": "rect",
      "interactive": true,
      "encode": {
        "update": {
          "x": {
            "scale": "x_0_tooltip",
            "field": "x_out"
          },
          "width": {
            "scale": "x_0_tooltip",
            "band": 1
          }
        }
      }
    }
  ]
}


Eric Socolofsky

unread,
Jan 24, 2018, 8:42:44 PM1/24/18
to vega-js
Correction, as shown in the spec snippet, this is a `type: time` scale.
Also, a clarification: I'd like to avoid translating/scaling the line chart; it should still occupy the entire width of the scale. Ideally, the first and last bands are centered on the left and right edges of the chart, so appear to be half the width of the other bands in between.

Roy I

unread,
Jan 25, 2018, 9:28:08 AM1/25/18
to vega-js
Instead of using "band" scale, position each "rect" item relative to the data point. If points always have the same time interval and there are no missing points, then just use "xc" to center. 

For more specific help, please post a complete Vega spec with example data.  

Eric Socolofsky

unread,
Jan 26, 2018, 1:18:20 AM1/26/18
to vega-js
That was enough to get me over the hump, thanks Roy!

I found that centering bands on points then revealed the problem that each band was too narrow, because N bands calculated to fill the chart width end up being spaced out a bit when instead centered on positions stretching from absolute left to right edges.

I managed to solve this by increasing my scale range to:

"range": [
    0,
    {"signal": "width * (data('output_0_0').length)/(data('output_0_0').length - 1)"}
]

Basically: count the data I'm rendering as discrete marks and expand the width of the range to fill the gaps between rects.
Reply all
Reply to author
Forward
0 new messages