diff --git a/examples/compiled/point_conditional_opacity.png b/examples/compiled/point_conditional_opacity.png new file mode 100644 index 0000000000..bf0665e286 Binary files /dev/null and b/examples/compiled/point_conditional_opacity.png differ diff --git a/examples/compiled/point_conditional_opacity.svg b/examples/compiled/point_conditional_opacity.svg new file mode 100644 index 0000000000..5a6551a88f --- /dev/null +++ b/examples/compiled/point_conditional_opacity.svg @@ -0,0 +1 @@ +050100150200Horsepower01020304050Miles_per_Gallon \ No newline at end of file diff --git a/examples/compiled/point_conditional_opacity.vg.json b/examples/compiled/point_conditional_opacity.vg.json new file mode 100644 index 0000000000..cc4f0ab685 --- /dev/null +++ b/examples/compiled/point_conditional_opacity.vg.json @@ -0,0 +1,113 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "style": "cell", + "data": [ + { + "name": "source_0", + "url": "data/cars.json", + "format": {"type": "json"}, + "transform": [ + { + "type": "filter", + "expr": "isValid(datum[\"Horsepower\"]) && isFinite(+datum[\"Horsepower\"]) && isValid(datum[\"Miles_per_Gallon\"]) && isFinite(+datum[\"Miles_per_Gallon\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "symbol", + "style": ["point"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"value": "transparent"}, + "stroke": {"value": "#4c78a8"}, + "opacity": [ + {"test": "datum.Horsepower > 100", "value": 0.25}, + {"value": 0.5} + ], + "ariaRoleDescription": {"value": "point"}, + "description": { + "signal": "\"Horsepower: \" + (format(datum[\"Horsepower\"], \"\")) + \"; Miles_per_Gallon: \" + (format(datum[\"Miles_per_Gallon\"], \"\"))" + }, + "x": {"scale": "x", "field": "Horsepower"}, + "y": {"scale": "y", "field": "Miles_per_Gallon"} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "linear", + "domain": {"data": "source_0", "field": "Horsepower"}, + "range": [0, {"signal": "width"}], + "nice": true, + "zero": true + }, + { + "name": "y", + "type": "linear", + "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, + "range": [{"signal": "height"}, 0], + "nice": true, + "zero": true + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickCount": {"signal": "ceil(width/40)"}, + "domain": false, + "labels": false, + "aria": false, + "maxExtent": 0, + "minExtent": 0, + "ticks": false, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "gridScale": "x", + "grid": true, + "tickCount": {"signal": "ceil(height/40)"}, + "domain": false, + "labels": false, + "aria": false, + "maxExtent": 0, + "minExtent": 0, + "ticks": false, + "zindex": 0 + }, + { + "scale": "x", + "orient": "bottom", + "grid": false, + "title": "Horsepower", + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "Miles_per_Gallon", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ], + "config": {"style": {"point": {"opacity": 0.5}}} +} diff --git a/examples/specs/point_conditional_opacity.vl.json b/examples/specs/point_conditional_opacity.vl.json new file mode 100644 index 0000000000..7b44efebba --- /dev/null +++ b/examples/specs/point_conditional_opacity.vl.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": {"url": "data/cars.json"}, + "mark": "point", + "encoding": { + "x": {"field": "Horsepower", "type": "quantitative"}, + "y": {"field": "Miles_per_Gallon", "type": "quantitative"}, + "opacity": { + "condition": [{"test": "datum.Horsepower > 100", "value": 0.25}] + } + }, + "config": {"point": {"opacity": 0.5}} +} diff --git a/src/compile/mark/encode/nonposition.ts b/src/compile/mark/encode/nonposition.ts index 3f2380d4d1..8ffe7b1ffa 100644 --- a/src/compile/mark/encode/nonposition.ts +++ b/src/compile/mark/encode/nonposition.ts @@ -1,6 +1,6 @@ import type {SignalRef} from 'vega'; import {NonPositionScaleChannel} from '../../../channel'; -import {Value} from '../../../channeldef'; +import {Value, isConditionalDef} from '../../../channeldef'; import {VgEncodeChannel, VgEncodeEntry, VgValueRef} from '../../../vega.schema'; import {getMarkPropOrConfig, signalOrValueRef} from '../../common'; import {UnitModel} from '../../unit'; @@ -24,16 +24,22 @@ export function nonPosition( const {vgChannel} = opt; let {defaultRef, defaultValue} = opt; + const channelDef = encoding[channel]; + if (defaultRef === undefined) { // prettier-ignore - defaultValue ??= getMarkPropOrConfig(channel, markDef, config, {vgChannel, ignoreVgConfig: true}); + defaultValue ??= getMarkPropOrConfig(channel, markDef, config, { + vgChannel, + // If there is no conditonal def, we ignore vgConfig so the output spec is concise. + // However, if there is a conditional def, we must include vgConfig so the default is respected. + ignoreVgConfig: !isConditionalDef(channelDef) + }); if (defaultValue !== undefined) { defaultRef = signalOrValueRef(defaultValue); } } - const channelDef = encoding[channel]; const commonProps = { markDef, config,