diff --git a/examples/compiled/bar_ranged_not_binned.png b/examples/compiled/bar_ranged_not_binned.png new file mode 100644 index 00000000000..40885562b47 Binary files /dev/null and b/examples/compiled/bar_ranged_not_binned.png differ diff --git a/examples/compiled/bar_ranged_not_binned.svg b/examples/compiled/bar_ranged_not_binned.svg new file mode 100644 index 00000000000..1ede95e7947 --- /dev/null +++ b/examples/compiled/bar_ranged_not_binned.svg @@ -0,0 +1 @@ +20406080100b020406080100b, b2 \ No newline at end of file diff --git a/examples/compiled/bar_ranged_not_binned.vg.json b/examples/compiled/bar_ranged_not_binned.vg.json new file mode 100644 index 00000000000..220fcb013bd --- /dev/null +++ b/examples/compiled/bar_ranged_not_binned.vg.json @@ -0,0 +1,123 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "style": "cell", + "data": [ + { + "name": "source_0", + "values": [ + {"b": 28, "b2": 0}, + {"b": 55, "b2": 0}, + {"b": 43, "b2": 0}, + {"b": 91, "b2": 0}, + {"b": 81, "b2": 0}, + {"b": 53, "b2": 0}, + {"b": 19, "b2": 0}, + {"b": 87, "b2": 0}, + {"b": 52, "b2": 0} + ] + }, + { + "name": "data_0", + "source": "source_0", + "transform": [ + { + "type": "filter", + "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "data_0"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"b: \" + (format(datum[\"b\"], \"\")) + \"; b2: \" + (format(datum[\"b2\"], \"\"))" + }, + "xc": {"scale": "x", "field": "b"}, + "width": {"value": 5}, + "y": {"scale": "y", "field": "b"}, + "y2": {"scale": "y", "field": "b2"} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "linear", + "domain": {"data": "data_0", "field": "b"}, + "range": [0, {"signal": "width"}], + "nice": true, + "zero": false, + "padding": 5 + }, + { + "name": "y", + "type": "linear", + "domain": {"data": "data_0", "fields": ["b", "b2"]}, + "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": "b", + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "b, b2", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ] +} diff --git a/examples/compiled/histogram_nonlinear.png b/examples/compiled/histogram_nonlinear.png index d062997056f..14fd59ba2fe 100644 Binary files a/examples/compiled/histogram_nonlinear.png and b/examples/compiled/histogram_nonlinear.png differ diff --git a/examples/compiled/histogram_nonlinear.svg b/examples/compiled/histogram_nonlinear.svg index c77d6080edb..3d5e576f930 100644 --- a/examples/compiled/histogram_nonlinear.svg +++ b/examples/compiled/histogram_nonlinear.svg @@ -1 +1 @@ -08.3312.5016.6733.3350.0066.6783.330%50%100%Distribution of Frame Render Time (ms) \ No newline at end of file +08.3312.5016.6733.3350.0066.6783.330%50%100%Distribution of Frame Render Time (ms) \ No newline at end of file diff --git a/examples/compiled/layer_cumulative_histogram.png b/examples/compiled/layer_cumulative_histogram.png index dfa42c17a0b..03ccb7fa23e 100644 Binary files a/examples/compiled/layer_cumulative_histogram.png and b/examples/compiled/layer_cumulative_histogram.png differ diff --git a/examples/compiled/layer_cumulative_histogram.svg b/examples/compiled/layer_cumulative_histogram.svg index 3c813842e89..ce83f716daa 100644 --- a/examples/compiled/layer_cumulative_histogram.svg +++ b/examples/compiled/layer_cumulative_histogram.svg @@ -1 +1 @@ -0246810IMDB Rating05001,0001,5002,0002,5003,000Cumulative Count, count \ No newline at end of file +246810IMDB Rating05001,0001,5002,0002,5003,000Cumulative Count, count \ No newline at end of file diff --git a/examples/compiled/layer_cumulative_histogram.vg.json b/examples/compiled/layer_cumulative_histogram.vg.json index 86f4c6f9c6b..eb388db23d1 100644 --- a/examples/compiled/layer_cumulative_histogram.vg.json +++ b/examples/compiled/layer_cumulative_histogram.vg.json @@ -47,6 +47,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["bin_IMDB_Rating", "bin_IMDB_Rating"], + "field": "Cumulative Count", + "sort": {"field": [], "order": []}, + "as": ["Cumulative Count_start", "Cumulative Count_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"bin_IMDB_Rating\"]) && isFinite(+datum[\"bin_IMDB_Rating\"]) && isValid(datum[\"Cumulative Count\"]) && isFinite(+datum[\"Cumulative Count\"])" @@ -57,6 +65,14 @@ "name": "data_1", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["bin_IMDB_Rating", "bin_IMDB_Rating"], + "field": "count", + "sort": {"field": [], "order": []}, + "as": ["count_start", "count_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"bin_IMDB_Rating\"]) && isFinite(+datum[\"bin_IMDB_Rating\"]) && isValid(datum[\"count\"]) && isFinite(+datum[\"count\"])" @@ -75,12 +91,12 @@ "fill": {"value": "#4c78a8"}, "ariaRoleDescription": {"value": "bar"}, "description": { - "signal": "\"IMDB Rating: \" + (format(datum[\"bin_IMDB_Rating\"], \"\")) + \"; Cumulative Count: \" + (format(datum[\"Cumulative Count\"], \"\")) + \"; bin_IMDB_Rating_end: \" + (format(datum[\"bin_IMDB_Rating_end\"], \"\"))" + "signal": "\"IMDB Rating: \" + (!isValid(datum[\"bin_IMDB_Rating\"]) || !isFinite(+datum[\"bin_IMDB_Rating\"]) ? \"null\" : format(datum[\"bin_IMDB_Rating\"], \"\") + \" – \" + format(datum[\"bin_IMDB_Rating_end\"], \"\")) + \"; Cumulative Count: \" + (format(datum[\"Cumulative Count\"], \"\"))" }, - "x": {"scale": "x", "field": "bin_IMDB_Rating"}, - "x2": {"scale": "x", "field": "bin_IMDB_Rating_end"}, - "y": {"scale": "y", "field": "Cumulative Count"}, - "y2": {"scale": "y", "value": 0} + "x2": {"scale": "x", "field": "bin_IMDB_Rating", "offset": 1}, + "x": {"scale": "x", "field": "bin_IMDB_Rating_end"}, + "y": {"scale": "y", "field": "Cumulative Count_end"}, + "y2": {"scale": "y", "field": "Cumulative Count_start"} } } }, @@ -95,12 +111,12 @@ "fill": {"value": "yellow"}, "ariaRoleDescription": {"value": "bar"}, "description": { - "signal": "\"IMDB Rating: \" + (format(datum[\"bin_IMDB_Rating\"], \"\")) + \"; count: \" + (format(datum[\"count\"], \"\")) + \"; bin_IMDB_Rating_end: \" + (format(datum[\"bin_IMDB_Rating_end\"], \"\"))" + "signal": "\"IMDB Rating: \" + (!isValid(datum[\"bin_IMDB_Rating\"]) || !isFinite(+datum[\"bin_IMDB_Rating\"]) ? \"null\" : format(datum[\"bin_IMDB_Rating\"], \"\") + \" – \" + format(datum[\"bin_IMDB_Rating_end\"], \"\")) + \"; count: \" + (format(datum[\"count\"], \"\"))" }, - "x": {"scale": "x", "field": "bin_IMDB_Rating"}, - "x2": {"scale": "x", "field": "bin_IMDB_Rating_end"}, - "y": {"scale": "y", "field": "count"}, - "y2": {"scale": "y", "value": 0} + "x2": {"scale": "x", "field": "bin_IMDB_Rating", "offset": 1}, + "x": {"scale": "x", "field": "bin_IMDB_Rating_end"}, + "y": {"scale": "y", "field": "count_end"}, + "y2": {"scale": "y", "field": "count_start"} } } } @@ -118,17 +134,17 @@ ] }, "range": [0, {"signal": "width"}], - "zero": false, - "nice": true, - "padding": 5 + "zero": false }, { "name": "y", "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "Cumulative Count"}, - {"data": "data_1", "field": "count"} + {"data": "data_0", "field": "Cumulative Count_start"}, + {"data": "data_0", "field": "Cumulative Count_end"}, + {"data": "data_1", "field": "count_start"}, + {"data": "data_1", "field": "count_end"} ] }, "range": [{"signal": "height"}, 0], @@ -137,20 +153,6 @@ } ], "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", diff --git a/examples/compiled/wheat_wages.png b/examples/compiled/wheat_wages.png index 67270dcb31a..1eb3eea86bc 100644 Binary files a/examples/compiled/wheat_wages.png and b/examples/compiled/wheat_wages.png differ diff --git a/examples/compiled/wheat_wages.svg b/examples/compiled/wheat_wages.svg index 6297842c354..d534496c1fb 100644 --- a/examples/compiled/wheat_wages.svg +++ b/examples/compiled/wheat_wages.svg @@ -1 +1 @@ -16001650170017501800ElizabethJames ICharles ICromwellCharles IIJames IIW&MAnneGeorge IGeorge IIGeorge IIIGeorge IV0102030405060708090100 \ No newline at end of file +16001650170017501800ElizabethJames ICharles ICromwellCharles IIJames IIW&MAnneGeorge IGeorge IIGeorge IIIGeorge IV0102030405060708090100 \ No newline at end of file diff --git a/examples/compiled/wheat_wages.vg.json b/examples/compiled/wheat_wages.vg.json index 64bd031025c..332b33349b1 100644 --- a/examples/compiled/wheat_wages.vg.json +++ b/examples/compiled/wheat_wages.vg.json @@ -33,6 +33,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["year", "year"], + "field": "wheat", + "sort": {"field": [], "order": []}, + "as": ["wheat_start", "wheat_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"year\"]) && isFinite(+datum[\"year\"]) && isValid(datum[\"wheat\"]) && isFinite(+datum[\"wheat\"])" @@ -98,12 +106,12 @@ "stroke": {"value": "#999"}, "ariaRoleDescription": {"value": "bar"}, "description": { - "signal": "\"year: \" + (format(datum[\"year\"], \"d\")) + \"; wheat: \" + (format(datum[\"wheat\"], \"\")) + \"; year_end: \" + (format(datum[\"year_end\"], \"\"))" + "signal": "\"year: \" + (!isValid(datum[\"year\"]) || !isFinite(+datum[\"year\"]) ? \"null\" : format(datum[\"year\"], \"d\") + \" – \" + format(datum[\"year_end\"], \"d\")) + \"; wheat: \" + (format(datum[\"wheat\"], \"\"))" }, - "x": {"scale": "x", "field": "year"}, - "x2": {"scale": "x", "field": "year_end"}, - "y": {"scale": "y", "field": "wheat"}, - "y2": {"scale": "y", "value": 0} + "x2": {"scale": "x", "field": "year", "offset": 1}, + "x": {"scale": "x", "field": "year_end"}, + "y": {"scale": "y", "field": "wheat_end"}, + "y2": {"scale": "y", "field": "wheat_start"} } } }, @@ -193,13 +201,12 @@ { "name": "layer_5_marks", "type": "rect", - "style": ["bar"], + "style": ["rect"], "from": {"data": "data_2"}, "encode": { "update": { "stroke": {"value": "#000"}, "fill": {"scale": "fill", "field": "commonwealth"}, - "ariaRoleDescription": {"value": "bar"}, "description": { "signal": "\"start: \" + (format(datum[\"start\"], \"d\")) + \"; y: \" + (format(datum[\"y\"], \"\")) + \"; end: \" + (format(datum[\"end\"], \"\")) + \"; offset: \" + (format(datum[\"offset\"], \"\")) + \"; commonwealth: \" + (isValid(datum[\"commonwealth\"]) ? datum[\"commonwealth\"] : \"\"+datum[\"commonwealth\"])" }, @@ -251,15 +258,15 @@ }, "range": [0, {"signal": "width"}], "nice": true, - "zero": false, - "padding": 5 + "zero": false }, { "name": "y", "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "wheat"}, + {"data": "data_0", "field": "wheat_start"}, + {"data": "data_0", "field": "wheat_end"}, {"data": "source_0", "field": "wages"}, {"data": "data_2", "field": "y"}, {"data": "data_2", "field": "offset"}, @@ -278,20 +285,6 @@ } ], "axes": [ - { - "scale": "x", - "orient": "bottom", - "tickCount": 5, - "gridScale": "y", - "grid": true, - "domain": false, - "labels": false, - "aria": false, - "maxExtent": 0, - "minExtent": 0, - "ticks": false, - "zindex": 0 - }, { "scale": "y", "orient": "left", diff --git a/examples/specs/bar_ranged_not_binned.vl.json b/examples/specs/bar_ranged_not_binned.vl.json new file mode 100644 index 00000000000..d8ca28ff022 --- /dev/null +++ b/examples/specs/bar_ranged_not_binned.vl.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": { + "values": [ + { "b": 28, "b2": 0}, { "b": 55, "b2": 0}, { "b": 43, "b2": 0}, + { "b": 91, "b2": 0}, { "b": 81, "b2": 0}, { "b": 53, "b2": 0}, + { "b": 19, "b2": 0}, { "b": 87, "b2": 0}, { "b": 52, "b2": 0} + ] + }, + "mark": {"type": "bar"}, + "encoding": { + "x": {"field": "b", "type": "quantitative"}, + "y": {"field": "b", "type": "quantitative"}, + "y2": {"field": "b2"} + } +} diff --git a/examples/specs/histogram_nonlinear.vl.json b/examples/specs/histogram_nonlinear.vl.json index ae56afc5be3..6a291c340fd 100644 --- a/examples/specs/histogram_nonlinear.vl.json +++ b/examples/specs/histogram_nonlinear.vl.json @@ -48,7 +48,7 @@ "title": "Distribution of Frame Render Time (ms)", "width": {"step": 40}, "height": 100, - "mark": {"type": "bar", "cornerRadiusEnd": 0}, + "mark": {"type": "bar", "cornerRadiusEnd": 0, "orient": "vertical"}, "encoding": { "x": { "title": "", diff --git a/examples/specs/layer_cumulative_histogram.vl.json b/examples/specs/layer_cumulative_histogram.vl.json index 2aa5682c7d6..d7e684a2416 100644 --- a/examples/specs/layer_cumulative_histogram.vl.json +++ b/examples/specs/layer_cumulative_histogram.vl.json @@ -19,7 +19,8 @@ "x": { "field": "bin_IMDB_Rating", "type": "quantitative", "scale": {"zero": false}, - "title": "IMDB Rating" + "title": "IMDB Rating", + "bin": "binned" }, "x2": {"field": "bin_IMDB_Rating_end"} }, diff --git a/examples/specs/normalized/layer_cumulative_histogram_normalized.vl.json b/examples/specs/normalized/layer_cumulative_histogram_normalized.vl.json index 66e87cd1d66..5814122d36f 100644 --- a/examples/specs/normalized/layer_cumulative_histogram_normalized.vl.json +++ b/examples/specs/normalized/layer_cumulative_histogram_normalized.vl.json @@ -9,7 +9,8 @@ "field": "bin_IMDB_Rating", "type": "quantitative", "scale": {"zero": false}, - "title": "IMDB Rating" + "title": "IMDB Rating", + "bin": "binned" }, "x2": {"field": "bin_IMDB_Rating_end"}, "y": {"field": "Cumulative Count", "type": "quantitative"} @@ -22,7 +23,8 @@ "field": "bin_IMDB_Rating", "type": "quantitative", "scale": {"zero": false}, - "title": "IMDB Rating" + "title": "IMDB Rating", + "bin": "binned" }, "x2": {"field": "bin_IMDB_Rating_end"}, "y": {"field": "count", "type": "quantitative"} diff --git a/examples/specs/normalized/wheat_wages_normalized.vl.json b/examples/specs/normalized/wheat_wages_normalized.vl.json index df4b388ba90..1b293e59da1 100644 --- a/examples/specs/normalized/wheat_wages_normalized.vl.json +++ b/examples/specs/normalized/wheat_wages_normalized.vl.json @@ -11,7 +11,8 @@ "x": { "type": "quantitative", "axis": {"tickCount": 5, "format": "d"}, - "field": "year" + "field": "year", + "bin": "binned" }, "x2": {"field": "year_end"} } @@ -75,7 +76,7 @@ }, { "data": {"url": "data/monarchs.json"}, - "mark": {"type": "bar", "stroke": "#000"}, + "mark": {"type": "rect", "stroke": "#000"}, "encoding": { "y": {"type": "quantitative", "axis": {"zindex": 1}, "field": "y"}, "x": { diff --git a/examples/specs/wheat_wages.vl.json b/examples/specs/wheat_wages.vl.json index 7eaf6de7c43..b79cad0beab 100644 --- a/examples/specs/wheat_wages.vl.json +++ b/examples/specs/wheat_wages.vl.json @@ -18,7 +18,7 @@ { "mark": {"type": "bar", "fill": "#aaa", "stroke": "#999"}, "encoding": { - "x": {"field": "year"}, + "x": {"field": "year", "bin":"binned"}, "x2": {"field": "year_end"}, "y": {"field": "wheat"} } @@ -74,7 +74,7 @@ { "calculate": "((!datum.commonwealth && datum.index % 2) ? -1: 1) * 2 + 95", "as": "offset" }, { "calculate": "95", "as": "y" } ], - "mark": {"type": "bar", "stroke": "#000"}, + "mark": {"type": "rect", "stroke": "#000"}, "encoding": { "x": {"field": "start"}, "x2": {"field": "end"}, diff --git a/src/compile/mark/init.ts b/src/compile/mark/init.ts index daa16460010..edd32312bd9 100644 --- a/src/compile/mark/init.ts +++ b/src/compile/mark/init.ts @@ -123,18 +123,24 @@ function orient(mark: Mark, encoding: Encoding, specifiedOrient: Orienta return specifiedOrient; } - // If y is range and x is non-range, non-bin Q, y is likely a prebinned field + // If y is range and x is non-range, non-bin Q if (!x2) { if ((isFieldDef(x) && x.type === QUANTITATIVE && !isBinning(x.bin)) || isNumericDataDef(x)) { - return 'horizontal'; + if (isFieldDef(y) && isBinned(y.bin)) { + return 'horizontal'; + } } + return 'vertical'; } - // If x is range and y is non-range, non-bin Q, x is likely a prebinned field + // If x is range and y is non-range, non-bin Q if (!y2) { if ((isFieldDef(y) && y.type === QUANTITATIVE && !isBinning(y.bin)) || isNumericDataDef(y)) { - return 'vertical'; + if (isFieldDef(x) && isBinned(x.bin)) { + return 'vertical'; + } } + return 'horizontal'; } } diff --git a/test/compile/mark/bar.test.ts b/test/compile/mark/bar.test.ts index 7c7d354843e..29fabebecd6 100644 --- a/test/compile/mark/bar.test.ts +++ b/test/compile/mark/bar.test.ts @@ -43,9 +43,9 @@ describe('Mark: Bar', () => { expect(props.height).toBeUndefined(); }); - it('should draw vertical bar, with y from zero to field value and bar with quantitative x, x2, and y', () => { - const x: PositionFieldDef = {field: 'bin_start', type: 'quantitative'}; - const x2: SecondaryFieldDef = {field: 'bin_end'}; + it('should draw horizontal bar, with y from zero to field value and bar with quantitative x, x2, and y', () => { + const x: PositionFieldDef = {field: 'q_start', type: 'quantitative'}; + const x2: SecondaryFieldDef = {field: 'q_end'}; const model = parseUnitModelWithScaleAndLayoutSize({ data: {url: 'data/cars.json'}, mark: 'bar', @@ -56,11 +56,30 @@ describe('Mark: Bar', () => { } }); const props = bar.encodeEntry(model); - expect(props.x).toEqual({scale: 'x', field: 'bin_start'}); - expect(props.x2).toEqual({scale: 'x', field: 'bin_end'}); - expect(props.y).toEqual({scale: 'y', field: 'Acceleration'}); + expect(props.x).toEqual({scale: 'x', field: 'q_start'}); + expect(props.x2).toEqual({scale: 'x', field: 'q_end'}); + expect(props.yc).toEqual({scale: 'y', field: 'Acceleration'}); + expect(props.y).toBeUndefined(); + expect(props.height).toEqual({value: defaultBarConfig.continuousBandSize}); + }); + + it('should draw vertical bar, with y from zero to field value and bar with binned x, x2, and y', () => { + const x: PositionFieldDef = {field: 'bin_start', type: 'quantitative', bin: 'binned'}; + const x2: SecondaryFieldDef = {field: 'bin_end'}; + const model = parseUnitModelWithScaleAndLayoutSize({ + data: {url: 'data/cars.json'}, + mark: 'bar', + encoding: { + x, + x2, + y: {type: 'quantitative', field: 'Acceleration', aggregate: 'mean'} + } + }); + const props = bar.encodeEntry(model); + expect(props.x).toEqual({scale: 'x', field: 'bin_end'}); + expect(props.x2).toEqual({scale: 'x', field: 'bin_start', offset: 1}); + expect(props.y).toEqual({scale: 'y', field: 'mean_Acceleration'}); expect(props.y2).toEqual({scale: 'y', value: 0}); - expect(props.height).toBeUndefined(); }); it('should draw vertical bar, with y from zero to field value and with band value for x/width when domain that includes zero is specified', () => { @@ -181,8 +200,8 @@ describe('Mark: Bar', () => { }); }); - it('should draw horizontal bar, with y from zero to field value and bar with quantitative x, x2, and y', () => { - const y: PositionFieldDef = {field: 'bin_start', type: 'quantitative'}; + it('should draw vertical bar, with y from zero to field value and bar with binned y, y2, and x', () => { + const y: PositionFieldDef = {field: 'bin_start', type: 'quantitative', bin: 'binned'}; const y2: SecondaryFieldDef = {field: 'bin_end'}; const model = parseUnitModelWithScaleAndLayoutSize({ data: {url: 'data/cars.json'}, @@ -190,15 +209,34 @@ describe('Mark: Bar', () => { encoding: { y, y2, - x: {type: 'quantitative', field: 'Acceleration'} + x: {type: 'quantitative', field: 'Acceleration', aggregate: 'mean'} } }); const props = bar.encodeEntry(model); - expect(props.y).toEqual({scale: 'y', field: 'bin_start'}); - expect(props.y2).toEqual({scale: 'y', field: 'bin_end'}); - expect(props.x).toEqual({scale: 'x', field: 'Acceleration'}); + expect(props.y).toEqual({scale: 'y', field: 'bin_end', offset: 1}); + expect(props.y2).toEqual({scale: 'y', field: 'bin_start'}); + expect(props.x).toEqual({scale: 'x', field: 'mean_Acceleration'}); expect(props.x2).toEqual({scale: 'x', value: 0}); - expect(props.height).toBeUndefined(); + }); + + it('should draw horizontal bar, with y from zero to field value and bar with quantitative y, y2, and x', () => { + const y: PositionFieldDef = {field: 'q_start', type: 'quantitative'}; + const y2: SecondaryFieldDef = {field: 'q_end'}; + const model = parseUnitModelWithScaleAndLayoutSize({ + data: {url: 'data/cars.json'}, + mark: 'bar', + encoding: { + y, + y2, + x: {type: 'quantitative', field: 'Acceleration'} + } + }); + const props = bar.encodeEntry(model); + expect(props.y).toEqual({scale: 'y', field: 'q_start'}); + expect(props.y2).toEqual({scale: 'y', field: 'q_end'}); + expect(props.xc).toEqual({scale: 'x', field: 'Acceleration'}); + expect(props.x).toBeUndefined(); + expect(props.width).toEqual({value: defaultBarConfig.continuousBandSize}); }); describe('simple horizontal with point scale', () => { diff --git a/test/compile/mark/init.test.ts b/test/compile/mark/init.test.ts index ae1ad161643..11556576cf0 100644 --- a/test/compile/mark/init.test.ts +++ b/test/compile/mark/init.test.ts @@ -383,6 +383,46 @@ describe('compile/mark/init', () => { expect(model.markDef.orient).toBe('horizontal'); }); + it('should return correct orient for bar with horizontal un-binned data', () => { + const model = parseUnitModelWithScaleAndLayoutSize({ + mark: 'bar', + encoding: { + x: { + field: 'q_start', + type: 'quantitative' + }, + x2: { + field: 'q_end' + }, + y: { + field: 'count', + type: 'quantitative' + } + } + }); + expect(model.markDef.orient).toBe('horizontal'); + }); + + it('should return correct orient for bar with vertical un-binned data', () => { + const model = parseUnitModelWithScaleAndLayoutSize({ + mark: 'bar', + encoding: { + y: { + field: 'q_start', + type: 'quantitative' + }, + y2: { + field: 'q_end' + }, + x: { + field: 'count', + type: 'quantitative' + } + } + }); + expect(model.markDef.orient).toBe('vertical'); + }); + it('should return correct orient for area with vertical binned data', () => { const model = parseUnitModelWithScaleAndLayoutSize({ mark: 'area',