Nate Richman
Nate Richman

Reputation: 23

Vega-lite interactive legend and bar chart

I'm fairly new to vega-lite. I'd really like to get the following interactive bar chart working:

My strategy for building this is to have two layers, one layer for the bars, and one for the text. Then one selection that is in 'multi' mode on mousedown, and also bound to the legend.

My question is two-fold:

  1. Is it possible to have a selection bound to the legend but also utilize mousedown?
  2. I'm having a hard time understanding how selections work in layered graphs/charts. If I define the selection outside of the layers I get a warning saying selection can't be found, and the selection only works as expected if I put it in the definition of the first layer. Additionally, the legend binding seems to work if I don't have layers, but stops working when I do have layers. Is this a limitation of the library or am I doing something wrong.

Here is my schema, thanks for any help in advance!

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "description": "A simple bar chart with embedded data.",
  "title": "test",
  "data": {
    "values": [
      ["Lateral", 630.666127],
      ["Basal", 413.211154],
      ["Accessory", 257.842981],
      ["Anterior", 48.735523],
      ["Central", 45.797799],
      ["Medial", 30.314856],
      ["Cortical", 27.697457],
      ["Corticoamygdaloid", 169.707268],
      ["Paralaminar", 46.216784],
      ["Whole_amygdala", 1670.189948]
    ],
    "name": "data"
  },
  "width": "600",
  "height": "400",
  "encoding": {
    "x": {"field": "0", "type": "nominal", "sort": "-y"},
    "y": {"field": "1", "type": "quantitative"}
  },
  "layer": [
    {
      "mark": "bar",
      "encoding": {
        "color": {
          "field": "0"
        },
        "opacity": {
          "condition": {"selection": "series", "value": 1},
          "value": 0.2
        }
      },
      "selection": {
        "series": {"type": "multi", "bind": "legend"}
      }
    },
    {
      "transform": [{"filter": {"selection":"series"}}],
      "mark": {"type": "text", "dy": -5},
      "encoding": {"text": {"field": "1"}}
    }
  ]
}

Upvotes: 2

Views: 2132

Answers (1)

jakevdp
jakevdp

Reputation: 86310

You were quite close. When you bind a selection to a legend, by default it deactivates other ways of interacting. But as mentioned briefly in the Legend Binding docs, you can re-enable this by specifying the "on" attribute. Here is the result (Open in editor):

{
  "title": "test",
  "data": {
    "values": [
      ["Lateral", 630.666127],
      ["Basal", 413.211154],
      ["Accessory", 257.842981],
      ["Anterior", 48.735523],
      ["Central", 45.797799],
      ["Medial", 30.314856],
      ["Cortical", 27.697457],
      ["Corticoamygdaloid", 169.707268],
      ["Paralaminar", 46.216784],
      ["Whole_amygdala", 1670.189948]
    ],
    "name": "data"
  },
  "width": "600",
  "height": "400",
  "encoding": {
    "x": {"field": "0", "type": "nominal", "sort": "-y"},
    "y": {"field": "1", "type": "quantitative"}
  },
  "layer": [
    {
      "mark": "bar",
      "encoding": {
        "color": {"field": "0"},
        "opacity": {
          "condition": {"selection": "series", "value": 1},
          "value": 0.2
        }
      },
      "selection": {
        "series": {
          "type": "multi",
          "encodings": ["color"],
          "on": "click",
          "bind": "legend"
        }
      }
    },
    {
      "transform": [{"filter": {"selection": "series"}}],
      "mark": {"type": "text", "dy": -5},
      "encoding": {"text": {"field": "1"}}
    }
  ]
}

enter image description here

Regarding your second question: currently selections must be defined within the layers they are bound to, but this will likely change in future Vega-Lite versions; see https://github.com/vega/vega-lite/pull/6919.

Upvotes: 1

Related Questions