vega-lite
vega-lite copied to clipboard
Erratic/broken field-based opacity range behavior if only a single value is used
Consider this:
{
"mark": {"type": "point"},
"encoding": {
"opacity": {
"field": "x",
"scale": {"range": {"field": "o"}},
"type": "nominal"
}
},
"transform": [{"calculate": "if(datum.x,0.5,1)", "as": "o"}],
"data": {"values": [{"x": false}, {"x": true}]}
}
This works perfectly fine:
So far so good.
But then watch what happens if I change true
for false
(or vice-versa):
{
"mark": {"type": "point"},
"encoding": {
"opacity": {
"field": "x",
"scale": {"range": {"field": "o"}},
"type": "nominal"
}
},
"transform": [{"calculate": "if(datum.x,0.5,1)", "as": "o"}],
"data": {"values": [{"x": false}, {"x": false}]}
}
Oops.
A similar problem occurs if I change the expression to just return a constant:
{
"mark": {"type": "point"},
"encoding": {
"opacity": {
"field": "x",
"scale": {"range": {"field": "o"}},
"type": "nominal"
}
},
"transform": [{"calculate": "1", "as": "o"}],
"data": {"values": [{"x": false}, {"x": true}]}
}
The issue can be seen in-browser and in the PNG exports above. However, somewhat mindbogglingly, SVG exports don't show the problem?!
It's also worth noting that while opacity
is affected, color
isn't:
{
"mark": {"type": "point"},
"encoding": {
"color": {
"field": "x",
"scale": {"range": {"field": "c"}},
"type": "nominal"
}
},
"transform": [{"calculate": "if(datum.x,'green','red')", "as": "c"}],
"data": {"values": [{"x": false}, {"x": false}]}
}
One workaround is to stop using a field range and use domain
instead:
{
"mark": {"type": "point"},
"encoding": {
"opacity": {
"field": "x",
"scale": {"domain": [false, true], "range": [1, 0.5]},
"type": "nominal"
}
},
"data": {"values": [{"x": false}, {"x": true}]}
}
However this may get messy as one will need to match the legend labels by hand, and more importantly this might not be an option if the domain is not known in advance.