vega / vega-lite

A concise grammar of interactive graphics, built on Vega.
https://vega.github.io/vega-lite/
BSD 3-Clause "New" or "Revised" License
4.68k stars 611 forks source link

Legend loses gradient if shared between layers #6258

Open dechamps opened 4 years ago

dechamps commented 4 years ago

The following:

{
  "layer": [{
    "mark": { "type": "line" },
    "encoding": {
      "color": {
        "type": "quantitative",
        "field": "c"
      }
    }
  }, {
    "mark": { "type": "circle" },
    "encoding": {
      "color": {
        "type": "quantitative",
        "field": "c"
      }
    }
  }],
  "data": {"values": [{"c": 1}, {"c": 2}]}
}

Currently produces:

visualization(50)

This is surprising - I would have expected a gradient legend.

If a layer is removed (which one is removed doesn't matter), the output is correct:

visualization(52)

dechamps commented 4 years ago

Up until vega-lite 4.8.0, I used to be able to work around this problem by setting legend to null in one of the layers. But sadly, that workaround doesn't work any more because of #6259.

domoritz commented 4 years ago

Thanks for the small example to reproduce the issue. That's very helpful.

The issue here is that we are adding symbolType although we should not be. It's probably a bug in the legend merge logic.

Screen Shot 2020-04-04 at 11 56 38
domoritz commented 4 years ago

We can force the legend type to be gradient. I wonder where we merge incorrectly 🤔

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "layer": [
    {
      "mark": {"type": "line"},
      "encoding": {
        "color": {
          "type": "quantitative",
          "field": "c",
          "legend": {"type": "gradient"}
        }
      }
    },
    {
      "mark": {"type": "circle"},
      "encoding": {"color": {"type": "quantitative", "field": "c"}}
    }
  ],
  "data": {"values": [{"c": 1}, {"c": 2}]}
}
dechamps commented 4 years ago

Yep, that workaround works with my chart. Thank you! Should have tried simply setting the type, seems obvious in retrospect :| I must have missed it in the legend property list.

Of course it would be even better if people didn't have to set the type explicitly, so I'll keep this open to fix the default behaviour.

domoritz commented 4 years ago

Completely agree. I'm just noting what I noticed in my debugging so far. We should fix the behavior.

domoritz commented 4 years ago

Okay, so the issue is that Vega uses a different legend when both fill and stroke are encoding a scale. That's a bit surprising but also kinda makes sense since only a symbol can encode both gradient and fill.

Removing one or the other does not make sense in the general case so I think that the behavior is actually as expected.

If you want a gradient legend, you need to tell Vega-Lite with "legend": {"type": "gradient"}.

kanitw commented 4 years ago

I don't think this is expected behavior

I think we could fix this in a few ways:

1) in Vega (when fill and stroke encodes the same color). or 2) encode "color" in legend parse and convert it to fill or stroke later in assemble.

That said, since there is a good workaround, I'll make this issue P3.

domoritz commented 4 years ago

Yes, Vega could make a different decision about showing data when only stroke and fill are encoded and they are encoded with the same scale. I also agree that it's low priority to change.