diff --git a/examples/compiled/bar_binned_yearmonth_grouped_center_band.png b/examples/compiled/bar_binned_yearmonth_grouped_center_band.png new file mode 100644 index 0000000000..c47310973c Binary files /dev/null and b/examples/compiled/bar_binned_yearmonth_grouped_center_band.png differ diff --git a/examples/compiled/bar_binned_yearmonth_grouped_center_band.svg b/examples/compiled/bar_binned_yearmonth_grouped_center_band.svg new file mode 100644 index 0000000000..1d3814b562 --- /dev/null +++ b/examples/compiled/bar_binned_yearmonth_grouped_center_band.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/bar_binned_yearmonth_grouped_center_band.vg.json b/examples/compiled/bar_binned_yearmonth_grouped_center_band.vg.json new file mode 100644 index 0000000000..addd923f0b --- /dev/null +++ b/examples/compiled/bar_binned_yearmonth_grouped_center_band.vg.json @@ -0,0 +1,171 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "description": "Stock price over time.", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "style": "cell", + "data": [ + { + "name": "source_0", + "url": "data/stocks.csv", + "format": {"type": "csv", "parse": {"date": "date"}}, + "transform": [ + { + "type": "filter", + "expr": "inrange(time(datum[\"date\"]), [time(datetime(2005, 0, 1, 0, 0, 0, 0)), time(datetime(2005, 2, 1, 0, 0, 0, 0))])" + }, + { + "type": "formula", + "expr": "timeOffset('month', datum['date'], 1)", + "as": "date_end" + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['date'], -1) + 0.5 * datum['date']", + "as": "date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['date'] + 0.5 * datum['date_end']", + "as": "date_offsetted_rect_end" + }, + { + "type": "stack", + "groupby": ["date", "symbol"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + }, + { + "type": "filter", + "expr": "(isDate(datum[\"date\"]) || (isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]))) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"scale": "color", "field": "symbol"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"date: \" + (timeFormat(datum[\"date\"], timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; price: \" + (format(datum[\"price\"], \"\")) + \"; symbol: \" + (isValid(datum[\"symbol\"]) ? datum[\"symbol\"] : \"\"+datum[\"symbol\"])" + }, + "xc": { + "scale": "x", + "field": "date", + "offset": {"scale": "xOffset", "field": "symbol", "band": 0.5} + }, + "width": {"signal": "max(0.25, bandwidth('xOffset'))"}, + "y": {"scale": "y", "field": "price_end"}, + "y2": {"scale": "y", "field": "price_start"} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "data": "source_0", + "fields": ["date_offsetted_rect_start", "date_offsetted_rect_end"] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "linear", + "domain": {"data": "source_0", "fields": ["price_start", "price_end"]}, + "range": [{"signal": "height"}, 0], + "nice": true, + "zero": true + }, + { + "name": "xOffset", + "type": "band", + "domain": {"data": "source_0", "field": "symbol", "sort": true}, + "range": [ + { + "signal": "-0.4 * (scale('x', datetime(2001, 1, 1, 0, 0, 0, 0)) - scale('x', datetime(2001, 0, 1, 0, 0, 0, 0)))" + }, + { + "signal": "0.4 * (scale('x', datetime(2001, 1, 1, 0, 0, 0, 0)) - scale('x', datetime(2001, 0, 1, 0, 0, 0, 0)))" + } + ] + }, + { + "name": "color", + "type": "ordinal", + "domain": {"data": "source_0", "field": "symbol", "sort": true}, + "range": "category" + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "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": "date", + "format": { + "signal": "timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "price", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ], + "legends": [{"fill": "color", "symbolType": "square", "title": "symbol"}] +} diff --git a/examples/compiled/bar_binned_yearmonth_label_band_center.png b/examples/compiled/bar_binned_yearmonth_label_band_center.png new file mode 100644 index 0000000000..76e09f342d Binary files /dev/null and b/examples/compiled/bar_binned_yearmonth_label_band_center.png differ diff --git a/examples/compiled/bar_binned_yearmonth_label_band_center.svg b/examples/compiled/bar_binned_yearmonth_label_band_center.svg new file mode 100644 index 0000000000..010afea05f --- /dev/null +++ b/examples/compiled/bar_binned_yearmonth_label_band_center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/bar_binned_yearmonth_label_band_center.vg.json b/examples/compiled/bar_binned_yearmonth_label_band_center.vg.json new file mode 100644 index 0000000000..91204d2334 --- /dev/null +++ b/examples/compiled/bar_binned_yearmonth_label_band_center.vg.json @@ -0,0 +1,205 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "description": "Google's stock price over time.", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "style": "cell", + "data": [ + { + "name": "source_0", + "url": "data/stocks.csv", + "format": {"type": "csv", "parse": {"date": "date"}}, + "transform": [ + {"type": "filter", "expr": "datum.symbol==='GOOG'"}, + { + "type": "filter", + "expr": "inrange(time(datum[\"date\"]), [time(datetime(2005, 0, 1, 0, 0, 0, 0)), time(datetime(2005, 2, 1, 0, 0, 0, 0))])" + } + ] + }, + { + "name": "data_0", + "source": "source_0", + "transform": [ + { + "type": "formula", + "expr": "timeOffset('month', datum['date'], 1)", + "as": "date_end" + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['date'], -1) + 0.5 * datum['date']", + "as": "date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['date'] + 0.5 * datum['date_end']", + "as": "date_offsetted_rect_end" + }, + { + "type": "stack", + "groupby": ["date"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + }, + { + "type": "filter", + "expr": "(isDate(datum[\"date\"]) || (isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]))) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" + } + ] + }, + { + "name": "data_1", + "source": "source_0", + "transform": [ + { + "type": "filter", + "expr": "(isDate(datum[\"date\"]) || (isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]))) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" + } + ] + } + ], + "marks": [ + { + "name": "layer_0_marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "data_0"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"date: \" + (timeFormat(datum[\"date\"], timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; price: \" + (format(datum[\"price\"], \"\"))" + }, + "x2": { + "scale": "x", + "field": "date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"date_end\"]) - scale(\"x\", datum[\"date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"x\", datum[\"date_end\"]) - scale(\"x\", datum[\"date\"])))) : 0.5)" + } + }, + "x": { + "scale": "x", + "field": "date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"date_end\"]) - scale(\"x\", datum[\"date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"x\", datum[\"date_end\"]) - scale(\"x\", datum[\"date\"])))) : -0.5)" + } + }, + "y": {"scale": "y", "field": "price_end"}, + "y2": {"scale": "y", "field": "price_start"} + } + } + }, + { + "name": "layer_1_marks", + "type": "text", + "style": ["text"], + "from": {"data": "data_1"}, + "encode": { + "update": { + "baseline": {"value": "bottom"}, + "fill": {"value": "black"}, + "description": { + "signal": "\"date: \" + (timeFormat(datum[\"date\"], timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; price: \" + (format(datum[\"price\"], \"\"))" + }, + "x": {"scale": "x", "field": "date"}, + "y": {"scale": "y", "field": "price"}, + "text": {"signal": "format(datum[\"price\"], \"\")"}, + "align": {"value": "center"} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "fields": [ + {"data": "data_0", "field": "date_offsetted_rect_start"}, + {"data": "data_0", "field": "date_offsetted_rect_end"}, + {"data": "data_1", "field": "date"}, + {"data": "data_1", "field": "date_end"} + ] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "linear", + "domain": { + "fields": [ + {"data": "data_0", "field": "price_start"}, + {"data": "data_0", "field": "price_end"}, + {"data": "data_1", "field": "price"} + ] + }, + "range": [{"signal": "height"}, 0], + "nice": true, + "zero": true + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "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": "date", + "format": { + "signal": "timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "price", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ] +} diff --git a/examples/compiled/bar_month_temporal_band_center.png b/examples/compiled/bar_month_temporal_band_center.png new file mode 100644 index 0000000000..62203cbc3b Binary files /dev/null and b/examples/compiled/bar_month_temporal_band_center.png differ diff --git a/examples/compiled/bar_month_temporal_band_center.svg b/examples/compiled/bar_month_temporal_band_center.svg new file mode 100644 index 0000000000..4c5776ae76 --- /dev/null +++ b/examples/compiled/bar_month_temporal_band_center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/bar_month_temporal_band_center.vg.json b/examples/compiled/bar_month_temporal_band_center.vg.json new file mode 100644 index 0000000000..597691718b --- /dev/null +++ b/examples/compiled/bar_month_temporal_band_center.vg.json @@ -0,0 +1,160 @@ +{ + "$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/seattle-weather.csv", + "format": {"type": "csv", "parse": {"date": "date"}}, + "transform": [ + { + "field": "date", + "type": "timeunit", + "units": ["month"], + "as": ["month_date", "month_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['month_date'], -1) + 0.5 * datum['month_date']", + "as": "month_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['month_date'] + 0.5 * datum['month_date_end']", + "as": "month_date_offsetted_rect_end" + }, + { + "type": "aggregate", + "groupby": [ + "month_date", + "month_date_end", + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ], + "ops": ["mean"], + "fields": ["precipitation"], + "as": ["mean_precipitation"] + }, + { + "type": "filter", + "expr": "(isDate(datum[\"month_date\"]) || (isValid(datum[\"month_date\"]) && isFinite(+datum[\"month_date\"]))) && isValid(datum[\"mean_precipitation\"]) && isFinite(+datum[\"mean_precipitation\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"date (month): \" + (timeFormat(datum[\"month_date\"], timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; Mean of precipitation: \" + (format(datum[\"mean_precipitation\"], \"\"))" + }, + "x2": { + "scale": "x", + "field": "month_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])))) : 0.5)" + } + }, + "x": { + "scale": "x", + "field": "month_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])))) : -0.5)" + } + }, + "y": {"scale": "y", "field": "mean_precipitation"}, + "y2": {"scale": "y", "value": 0} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "linear", + "domain": {"data": "source_0", "field": "mean_precipitation"}, + "range": [{"signal": "height"}, 0], + "nice": true, + "zero": true + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "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": "date (month)", + "format": { + "signal": "timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelFlush": true, + "labelOverlap": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "Mean of precipitation", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ] +} diff --git a/examples/compiled/bar_month_temporal_band_center_config.png b/examples/compiled/bar_month_temporal_band_center_config.png new file mode 100644 index 0000000000..62203cbc3b Binary files /dev/null and b/examples/compiled/bar_month_temporal_band_center_config.png differ diff --git a/examples/compiled/bar_month_temporal_band_center_config.svg b/examples/compiled/bar_month_temporal_band_center_config.svg new file mode 100644 index 0000000000..4c5776ae76 --- /dev/null +++ b/examples/compiled/bar_month_temporal_band_center_config.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/bar_month_temporal_band_center_config.vg.json b/examples/compiled/bar_month_temporal_band_center_config.vg.json new file mode 100644 index 0000000000..597691718b --- /dev/null +++ b/examples/compiled/bar_month_temporal_band_center_config.vg.json @@ -0,0 +1,160 @@ +{ + "$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/seattle-weather.csv", + "format": {"type": "csv", "parse": {"date": "date"}}, + "transform": [ + { + "field": "date", + "type": "timeunit", + "units": ["month"], + "as": ["month_date", "month_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['month_date'], -1) + 0.5 * datum['month_date']", + "as": "month_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['month_date'] + 0.5 * datum['month_date_end']", + "as": "month_date_offsetted_rect_end" + }, + { + "type": "aggregate", + "groupby": [ + "month_date", + "month_date_end", + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ], + "ops": ["mean"], + "fields": ["precipitation"], + "as": ["mean_precipitation"] + }, + { + "type": "filter", + "expr": "(isDate(datum[\"month_date\"]) || (isValid(datum[\"month_date\"]) && isFinite(+datum[\"month_date\"]))) && isValid(datum[\"mean_precipitation\"]) && isFinite(+datum[\"mean_precipitation\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"date (month): \" + (timeFormat(datum[\"month_date\"], timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; Mean of precipitation: \" + (format(datum[\"mean_precipitation\"], \"\"))" + }, + "x2": { + "scale": "x", + "field": "month_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])))) : 0.5)" + } + }, + "x": { + "scale": "x", + "field": "month_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"x\", datum[\"month_date_end\"]) - scale(\"x\", datum[\"month_date\"])))) : -0.5)" + } + }, + "y": {"scale": "y", "field": "mean_precipitation"}, + "y2": {"scale": "y", "value": 0} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "linear", + "domain": {"data": "source_0", "field": "mean_precipitation"}, + "range": [{"signal": "height"}, 0], + "nice": true, + "zero": true + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "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": "date (month)", + "format": { + "signal": "timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelFlush": true, + "labelOverlap": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "Mean of precipitation", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ] +} diff --git a/examples/compiled/bar_simple_binned_timeunit_special_chars.vg.json b/examples/compiled/bar_simple_binned_timeunit_special_chars.vg.json index 191f43dd0d..2fb873170f 100644 --- a/examples/compiled/bar_simple_binned_timeunit_special_chars.vg.json +++ b/examples/compiled/bar_simple_binned_timeunit_special_chars.vg.json @@ -31,7 +31,7 @@ {"type": "formula", "expr": "toDate(datum[\"a.b\"])", "as": "a.b"}, { "type": "formula", - "expr": "timeOffset('date', datum['a.b'], 1)", + "expr": "utcOffset('date', datum['a.b'], 1)", "as": "a.b_end" }, { diff --git a/examples/compiled/bar_yearmonth_center_band.png b/examples/compiled/bar_yearmonth_center_band.png new file mode 100644 index 0000000000..4ac977a0c8 Binary files /dev/null and b/examples/compiled/bar_yearmonth_center_band.png differ diff --git a/examples/compiled/bar_yearmonth_center_band.svg b/examples/compiled/bar_yearmonth_center_band.svg new file mode 100644 index 0000000000..4e3fa4a8cc --- /dev/null +++ b/examples/compiled/bar_yearmonth_center_band.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/bar_yearmonth_center_band.vg.json b/examples/compiled/bar_yearmonth_center_band.vg.json new file mode 100644 index 0000000000..4886b6c607 --- /dev/null +++ b/examples/compiled/bar_yearmonth_center_band.vg.json @@ -0,0 +1,163 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "description": "Temperature in Seattle as a bar chart with yearmonth time unit.", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "style": "cell", + "data": [ + { + "name": "source_0", + "url": "data/seattle-weather.csv", + "format": {"type": "csv", "parse": {"date": "date"}}, + "transform": [ + { + "field": "date", + "type": "timeunit", + "units": ["year", "month"], + "as": ["yearmonth_date", "yearmonth_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['yearmonth_date'], -1) + 0.5 * datum['yearmonth_date']", + "as": "yearmonth_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['yearmonth_date'] + 0.5 * datum['yearmonth_date_end']", + "as": "yearmonth_date_offsetted_rect_end" + }, + { + "type": "aggregate", + "groupby": [ + "yearmonth_date", + "yearmonth_date_end", + "yearmonth_date_offsetted_rect_start", + "yearmonth_date_offsetted_rect_end" + ], + "ops": ["mean"], + "fields": ["temp_max"], + "as": ["mean_temp_max"] + }, + { + "type": "filter", + "expr": "(isDate(datum[\"yearmonth_date\"]) || (isValid(datum[\"yearmonth_date\"]) && isFinite(+datum[\"yearmonth_date\"]))) && isValid(datum[\"mean_temp_max\"]) && isFinite(+datum[\"mean_temp_max\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"date (year-month): \" + (timeFormat(datum[\"yearmonth_date\"], timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; Mean of temp_max: \" + (format(datum[\"mean_temp_max\"], \"\"))" + }, + "x2": { + "scale": "x", + "field": "yearmonth_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"yearmonth_date_end\"]) - scale(\"x\", datum[\"yearmonth_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"x\", datum[\"yearmonth_date_end\"]) - scale(\"x\", datum[\"yearmonth_date\"])))) : 0.5)" + } + }, + "x": { + "scale": "x", + "field": "yearmonth_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"yearmonth_date_end\"]) - scale(\"x\", datum[\"yearmonth_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"x\", datum[\"yearmonth_date_end\"]) - scale(\"x\", datum[\"yearmonth_date\"])))) : -0.5)" + } + }, + "y": {"scale": "y", "field": "mean_temp_max"}, + "y2": {"scale": "y", "value": 0} + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "yearmonth_date_offsetted_rect_start", + "yearmonth_date_offsetted_rect_end" + ] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "linear", + "domain": {"data": "source_0", "field": "mean_temp_max"}, + "range": [{"signal": "height"}, 0], + "nice": true, + "zero": true + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "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": "date (year-month)", + "format": { + "signal": "timeUnitSpecifier([\"year\",\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "Mean of temp_max", + "labelOverlap": true, + "tickCount": {"signal": "ceil(height/40)"}, + "zindex": 0 + } + ] +} diff --git a/examples/compiled/rect_heatmap_weather_temporal_center_band.png b/examples/compiled/rect_heatmap_weather_temporal_center_band.png new file mode 100644 index 0000000000..1e05b81d86 Binary files /dev/null and b/examples/compiled/rect_heatmap_weather_temporal_center_band.png differ diff --git a/examples/compiled/rect_heatmap_weather_temporal_center_band.svg b/examples/compiled/rect_heatmap_weather_temporal_center_band.svg new file mode 100644 index 0000000000..52c09d0b29 --- /dev/null +++ b/examples/compiled/rect_heatmap_weather_temporal_center_band.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/rect_heatmap_weather_temporal_center_band.vg.json b/examples/compiled/rect_heatmap_weather_temporal_center_band.vg.json new file mode 100644 index 0000000000..ddafffe73d --- /dev/null +++ b/examples/compiled/rect_heatmap_weather_temporal_center_band.vg.json @@ -0,0 +1,223 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "title": { + "text": "Daily Max Temperatures (C) in Seattle, WA", + "frame": "group" + }, + "style": "cell", + "data": [ + { + "name": "source_0", + "url": "data/seattle-weather.csv", + "format": { + "type": "csv", + "parse": {"date": "date", "temp_max": "number"} + }, + "transform": [ + { + "field": "date", + "type": "timeunit", + "units": ["date"], + "as": ["date_date", "date_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('date', datum['date_date'], -1) + 0.5 * datum['date_date']", + "as": "date_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['date_date'] + 0.5 * datum['date_date_end']", + "as": "date_date_offsetted_rect_end" + }, + { + "field": "date", + "type": "timeunit", + "units": ["month"], + "as": ["month_date", "month_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['month_date'], -1) + 0.5 * datum['month_date']", + "as": "month_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['month_date'] + 0.5 * datum['month_date_end']", + "as": "month_date_offsetted_rect_end" + }, + { + "type": "aggregate", + "groupby": [ + "date_date", + "date_date_end", + "date_date_offsetted_rect_start", + "date_date_offsetted_rect_end", + "month_date", + "month_date_end", + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ], + "ops": ["max"], + "fields": ["temp_max"], + "as": ["max_temp_max"] + }, + { + "type": "filter", + "expr": "(isDate(datum[\"month_date\"]) || (isValid(datum[\"month_date\"]) && isFinite(+datum[\"month_date\"]))) && isValid(datum[\"max_temp_max\"]) && isFinite(+datum[\"max_temp_max\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["rect"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"scale": "color", "field": "max_temp_max"}, + "description": { + "signal": "\"Day: \" + (timeFormat(datum[\"date_date\"], '%e')) + \"; Month: \" + (timeFormat(datum[\"month_date\"], timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; Max of temp_max: \" + (format(datum[\"max_temp_max\"], \"\"))" + }, + "x2": { + "scale": "x", + "field": "date_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])))) : 0)" + } + }, + "x": { + "scale": "x", + "field": "date_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])))) : 0)" + } + }, + "y2": { + "scale": "y", + "field": "month_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])))) : 0)" + } + }, + "y": { + "scale": "y", + "field": "month_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])))) : 0)" + } + } + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "date_date_offsetted_rect_start", + "date_date_offsetted_rect_end" + ] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ] + }, + "range": [{"signal": "height"}, 0] + }, + { + "name": "color", + "type": "linear", + "domain": {"data": "source_0", "field": "max_temp_max"}, + "range": "heatmap", + "interpolate": "hcl", + "zero": false + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 0, 2, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "domain": false, + "labels": false, + "aria": false, + "maxExtent": 0, + "minExtent": 0, + "ticks": false, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "gridScale": "x", + "grid": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "domain": false, + "labels": false, + "aria": false, + "maxExtent": 0, + "minExtent": 0, + "ticks": false, + "zindex": 0 + }, + { + "scale": "x", + "orient": "bottom", + "grid": false, + "title": "Day", + "format": "%e", + "labelAngle": 0, + "labelBaseline": "top", + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 0, 2, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "Month", + "format": { + "signal": "timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelOverlap": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + } + ], + "legends": [ + {"fill": "color", "gradientLength": {"signal": "clamp(height, 64, 200)"}} + ], + "config": {"axis": {"domain": false}, "style": {"cell": {"strokeWidth": 0}}} +} diff --git a/examples/compiled/rect_heatmap_weather_temporal_center_band_config.png b/examples/compiled/rect_heatmap_weather_temporal_center_band_config.png new file mode 100644 index 0000000000..1e05b81d86 Binary files /dev/null and b/examples/compiled/rect_heatmap_weather_temporal_center_band_config.png differ diff --git a/examples/compiled/rect_heatmap_weather_temporal_center_band_config.svg b/examples/compiled/rect_heatmap_weather_temporal_center_band_config.svg new file mode 100644 index 0000000000..52c09d0b29 --- /dev/null +++ b/examples/compiled/rect_heatmap_weather_temporal_center_band_config.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/compiled/rect_heatmap_weather_temporal_center_band_config.vg.json b/examples/compiled/rect_heatmap_weather_temporal_center_band_config.vg.json new file mode 100644 index 0000000000..ddafffe73d --- /dev/null +++ b/examples/compiled/rect_heatmap_weather_temporal_center_band_config.vg.json @@ -0,0 +1,223 @@ +{ + "$schema": "https://vega.github.io/schema/vega/v5.json", + "background": "white", + "padding": 5, + "width": 200, + "height": 200, + "title": { + "text": "Daily Max Temperatures (C) in Seattle, WA", + "frame": "group" + }, + "style": "cell", + "data": [ + { + "name": "source_0", + "url": "data/seattle-weather.csv", + "format": { + "type": "csv", + "parse": {"date": "date", "temp_max": "number"} + }, + "transform": [ + { + "field": "date", + "type": "timeunit", + "units": ["date"], + "as": ["date_date", "date_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('date', datum['date_date'], -1) + 0.5 * datum['date_date']", + "as": "date_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['date_date'] + 0.5 * datum['date_date_end']", + "as": "date_date_offsetted_rect_end" + }, + { + "field": "date", + "type": "timeunit", + "units": ["month"], + "as": ["month_date", "month_date_end"] + }, + { + "type": "formula", + "expr": "0.5 * timeOffset('month', datum['month_date'], -1) + 0.5 * datum['month_date']", + "as": "month_date_offsetted_rect_start" + }, + { + "type": "formula", + "expr": "0.5 * datum['month_date'] + 0.5 * datum['month_date_end']", + "as": "month_date_offsetted_rect_end" + }, + { + "type": "aggregate", + "groupby": [ + "date_date", + "date_date_end", + "date_date_offsetted_rect_start", + "date_date_offsetted_rect_end", + "month_date", + "month_date_end", + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ], + "ops": ["max"], + "fields": ["temp_max"], + "as": ["max_temp_max"] + }, + { + "type": "filter", + "expr": "(isDate(datum[\"month_date\"]) || (isValid(datum[\"month_date\"]) && isFinite(+datum[\"month_date\"]))) && isValid(datum[\"max_temp_max\"]) && isFinite(+datum[\"max_temp_max\"])" + } + ] + } + ], + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["rect"], + "from": {"data": "source_0"}, + "encode": { + "update": { + "fill": {"scale": "color", "field": "max_temp_max"}, + "description": { + "signal": "\"Day: \" + (timeFormat(datum[\"date_date\"], '%e')) + \"; Month: \" + (timeFormat(datum[\"month_date\"], timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; Max of temp_max: \" + (format(datum[\"max_temp_max\"], \"\"))" + }, + "x2": { + "scale": "x", + "field": "date_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])))) : 0)" + } + }, + "x": { + "scale": "x", + "field": "date_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"x\", datum[\"date_date_end\"]) - scale(\"x\", datum[\"date_date\"])))) : 0)" + } + }, + "y2": { + "scale": "y", + "field": "month_date_offsetted_rect_start", + "offset": { + "signal": "0.5 + (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])) < 0.25 ? 0.5 * (0.25 - (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])))) : 0)" + } + }, + "y": { + "scale": "y", + "field": "month_date_offsetted_rect_end", + "offset": { + "signal": "0.5 + (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])) < 0.25 ? -0.5 * (0.25 - (abs(scale(\"y\", datum[\"month_date_end\"]) - scale(\"y\", datum[\"month_date\"])))) : 0)" + } + } + } + } + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "date_date_offsetted_rect_start", + "date_date_offsetted_rect_end" + ] + }, + "range": [0, {"signal": "width"}] + }, + { + "name": "y", + "type": "time", + "domain": { + "data": "source_0", + "fields": [ + "month_date_offsetted_rect_start", + "month_date_offsetted_rect_end" + ] + }, + "range": [{"signal": "height"}, 0] + }, + { + "name": "color", + "type": "linear", + "domain": {"data": "source_0", "field": "max_temp_max"}, + "range": "heatmap", + "interpolate": "hcl", + "zero": false + } + ], + "axes": [ + { + "scale": "x", + "orient": "bottom", + "gridScale": "y", + "grid": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 0, 2, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "domain": false, + "labels": false, + "aria": false, + "maxExtent": 0, + "minExtent": 0, + "ticks": false, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "gridScale": "x", + "grid": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "domain": false, + "labels": false, + "aria": false, + "maxExtent": 0, + "minExtent": 0, + "ticks": false, + "zindex": 0 + }, + { + "scale": "x", + "orient": "bottom", + "grid": false, + "title": "Day", + "format": "%e", + "labelAngle": 0, + "labelBaseline": "top", + "labelFlush": true, + "labelOverlap": true, + "tickCount": {"signal": "ceil(width/40)"}, + "tickMinStep": { + "signal": "datetime(2001, 0, 2, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + }, + { + "scale": "y", + "orient": "left", + "grid": false, + "title": "Month", + "format": { + "signal": "timeUnitSpecifier([\"month\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})" + }, + "labelOverlap": true, + "tickMinStep": { + "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)" + }, + "zindex": 0 + } + ], + "legends": [ + {"fill": "color", "gradientLength": {"signal": "clamp(height, 64, 200)"}} + ], + "config": {"axis": {"domain": false}, "style": {"cell": {"strokeWidth": 0}}} +} diff --git a/examples/compiled/time_parse_binnedutc.vg.json b/examples/compiled/time_parse_binnedutc.vg.json index a739f18cb5..55dc8f7d78 100644 --- a/examples/compiled/time_parse_binnedutc.vg.json +++ b/examples/compiled/time_parse_binnedutc.vg.json @@ -16,7 +16,7 @@ {"type": "formula", "expr": "toDate(datum[\"date\"])", "as": "date"}, { "type": "formula", - "expr": "timeOffset('hours', datum['date'], 1)", + "expr": "utcOffset('hours', datum['date'], 1)", "as": "date_end" } ] diff --git a/examples/specs/bar_binned_yearmonth_grouped_center_band.vl.json b/examples/specs/bar_binned_yearmonth_grouped_center_band.vl.json new file mode 100644 index 0000000000..56c854dc14 --- /dev/null +++ b/examples/specs/bar_binned_yearmonth_grouped_center_band.vl.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "description": "Stock price over time.", + "data": {"url": "data/stocks.csv"}, + "transform": [ + {"filter": {"timeUnit": "binnedyearmonth", "field": "date", "range": [{"year": 2005, "month": 1}, {"year": 2005, "month": 3}]}} + ], + "mark": "bar", + "encoding": { + "x": {"timeUnit": "binnedyearmonth", "field": "date", "type": "temporal", "bandPosition": 0}, + "xOffset": {"field": "symbol", "type": "nominal"}, + "color": {"field": "symbol", "type": "nominal"}, + "y": {"field": "price", "type": "quantitative"} + } +} diff --git a/examples/specs/bar_binned_yearmonth_label_band_center.vl.json b/examples/specs/bar_binned_yearmonth_label_band_center.vl.json new file mode 100644 index 0000000000..798a6d11ec --- /dev/null +++ b/examples/specs/bar_binned_yearmonth_label_band_center.vl.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "description": "Google's stock price over time.", + "data": {"url": "data/stocks.csv"}, + "transform": [ + {"filter": "datum.symbol==='GOOG'"}, + {"filter": {"timeUnit": "binnedyearmonth", "field": "date", "range": [{"year": 2005, "month": 1}, {"year": 2005, "month": 3}]}} + ], + "encoding": { + "x": {"timeUnit": "binnedyearmonth", "field": "date", "type": "temporal", "bandPosition": 0}, + "y": {"field": "price", "type": "quantitative"} + }, + "layer": [{ + "mark": "bar" + }, { + "mark": {"type": "text", "baseline": "bottom"}, + "encoding": { + "text": {"field": "price", "type": "quantitative"} + } + }] +} diff --git a/examples/specs/bar_month_temporal_band_center.vl.json b/examples/specs/bar_month_temporal_band_center.vl.json new file mode 100644 index 0000000000..d8ef4102c3 --- /dev/null +++ b/examples/specs/bar_month_temporal_band_center.vl.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": {"url": "data/seattle-weather.csv"}, + "mark": "bar", + "encoding": { + "x": {"timeUnit": "month", "field": "date", "type": "temporal", "bandPosition": 0}, + "y": {"aggregate": "mean", "field": "precipitation"} + } +} diff --git a/examples/specs/bar_month_temporal_band_center_config.vl.json b/examples/specs/bar_month_temporal_band_center_config.vl.json new file mode 100644 index 0000000000..7d8c05b428 --- /dev/null +++ b/examples/specs/bar_month_temporal_band_center_config.vl.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": {"url": "data/seattle-weather.csv"}, + "mark": "bar", + "encoding": { + "x": {"timeUnit": "month", "field": "date", "type": "temporal"}, + "y": {"aggregate": "mean", "field": "precipitation"} + }, + "config": { + "bar": {"timeUnitBandPosition": 0} + } +} diff --git a/examples/specs/bar_yearmonth_center_band.vl.json b/examples/specs/bar_yearmonth_center_band.vl.json new file mode 100644 index 0000000000..69128eb98b --- /dev/null +++ b/examples/specs/bar_yearmonth_center_band.vl.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "description": "Temperature in Seattle as a bar chart with yearmonth time unit.", + "data": {"url": "data/seattle-weather.csv"}, + "mark": "bar", + "encoding": { + "x": {"timeUnit": "yearmonth", "field": "date", "bandPosition": 0}, + "y": {"aggregate": "mean", "field": "temp_max"} + } +} diff --git a/examples/specs/normalized/bar_binned_yearmonth_label_band_center_normalized.vl.json b/examples/specs/normalized/bar_binned_yearmonth_label_band_center_normalized.vl.json new file mode 100644 index 0000000000..7ab0179750 --- /dev/null +++ b/examples/specs/normalized/bar_binned_yearmonth_label_band_center_normalized.vl.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "description": "Google's stock price over time.", + "data": {"url": "data/stocks.csv"}, + "layer": [ + { + "mark": "bar", + "encoding": { + "x": { + "timeUnit": "binnedyearmonth", + "field": "date", + "type": "temporal", + "bandPosition": 0 + }, + "y": {"field": "price", "type": "quantitative"} + } + }, + { + "mark": {"type": "text", "baseline": "bottom"}, + "encoding": { + "x": { + "timeUnit": "binnedyearmonth", + "field": "date", + "type": "temporal", + "bandPosition": 0 + }, + "y": {"field": "price", "type": "quantitative"}, + "text": {"field": "price", "type": "quantitative"} + } + } + ], + "transform": [ + {"filter": "datum.symbol==='GOOG'"}, + { + "filter": { + "timeUnit": "binnedyearmonth", + "field": "date", + "range": [{"year": 2005, "month": 1}, {"year": 2005, "month": 3}] + } + } + ] +} \ No newline at end of file diff --git a/examples/specs/rect_heatmap_weather_temporal_center_band.vl.json b/examples/specs/rect_heatmap_weather_temporal_center_band.vl.json new file mode 100644 index 0000000000..5697820e15 --- /dev/null +++ b/examples/specs/rect_heatmap_weather_temporal_center_band.vl.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": { + "url": "data/seattle-weather.csv" + }, + "title": "Daily Max Temperatures (C) in Seattle, WA", + "config": { + "view": { + "strokeWidth": 0, + "step": 13 + }, + "axis": { + "domain": false + } + }, + "mark": "rect", + "encoding": { + "x": { + "field": "date", + "timeUnit": "date", + "type": "temporal", + "title": "Day", + "bandPosition": 0, + "axis": { + "labelAngle": 0, + "format": "%e" + } + }, + "y": { + "field": "date", + "timeUnit": "month", + "bandPosition": 0, + "type": "temporal", + "title": "Month" + }, + "color": { + "field": "temp_max", + "aggregate": "max", + "type": "quantitative", + "legend": { + "title": null + } + } + } +} diff --git a/examples/specs/rect_heatmap_weather_temporal_center_band_config.vl.json b/examples/specs/rect_heatmap_weather_temporal_center_band_config.vl.json new file mode 100644 index 0000000000..d00e44abbf --- /dev/null +++ b/examples/specs/rect_heatmap_weather_temporal_center_band_config.vl.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": { + "url": "data/seattle-weather.csv" + }, + "title": "Daily Max Temperatures (C) in Seattle, WA", + "config": { + "view": { + "strokeWidth": 0, + "step": 13 + }, + "axis": { + "domain": false + }, + "rect": { + "timeUnitBandPosition": 0 + } + }, + "mark": "rect", + "encoding": { + "x": { + "field": "date", + "timeUnit": "date", + "type": "temporal", + "title": "Day", + "axis": { + "labelAngle": 0, + "format": "%e" + } + }, + "y": { + "field": "date", + "timeUnit": "month", + "type": "temporal", + "title": "Month" + }, + "color": { + "field": "temp_max", + "aggregate": "max", + "type": "quantitative", + "legend": { + "title": null + } + } + } +} diff --git a/site/_data/examples.json b/site/_data/examples.json index 94159777c3..a1fab1f006 100644 --- a/site/_data/examples.json +++ b/site/_data/examples.json @@ -84,6 +84,10 @@ "name": "bar_month_temporal_initial", "title": "Bar Chart showing Initials of Month Names" }, + { + "name": "bar_month_temporal_band_center", + "title": "Bar Chart with bars center-aligned with time unit ticks" + }, { "name": "bar_negative", "title": "Bar Chart with Negative Values and a Zero-Baseline" diff --git a/site/_includes/docs_toc.md b/site/_includes/docs_toc.md index 3e5e066297..c1d1174988 100644 --- a/site/_includes/docs_toc.md +++ b/site/_includes/docs_toc.md @@ -228,8 +228,8 @@ - [Documentation Overview]({{site.baseurl}}/docs/axis.html#documentation-overview) - [Axis Properties]({{site.baseurl}}/docs/axis.html#axis-properties) - [Axis Config]({{site.baseurl}}/docs/axis.html#config) - - [Band]({{site.baseurl}}/docs/band.html) - - [Examples]({{site.baseurl}}/docs/band.html#examples) + - [Band Position]({{site.baseurl}}/docs/bandposition.html) + - [Examples]({{site.baseurl}}/docs/bandposition.html#examples) - [Bin]({{site.baseurl}}/docs/bin.html) - [Documentation Overview]({{site.baseurl}}/docs/bin.html#documentation-overview) - [Binning in Encoding Field Definition]({{site.baseurl}}/docs/bin.html#encoding) diff --git a/site/_layouts/docs.html b/site/_layouts/docs.html index c46a28c6e0..5dc0b66848 100644 --- a/site/_layouts/docs.html +++ b/site/_layouts/docs.html @@ -98,8 +98,8 @@ url: aggregate - text: Axis url: axis - - text: Band - url: band + - text: Band Position + url: bandposition - text: Bin url: bin - text: Condition diff --git a/site/docs/encoding/band.md b/site/docs/encoding/band.md deleted file mode 100644 index e5d15520cd..0000000000 --- a/site/docs/encoding/band.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: docs -title: Band -permalink: /docs/band.html ---- - -Band properties can be used to adjust mark bandwidth or position for band scales, bin intervals, or time unit intervals. - -{% include table.html props="band" source="DatumDef" %} - -## Examples - -### Line Position - -By default, points in line marks are placed at the beginning of a time interval (e.g., "month"): - -
- -Setting `band` to `0.5` moves the points to the middle of the time interval. - - diff --git a/site/docs/encoding/bandPosition.md b/site/docs/encoding/bandPosition.md new file mode 100644 index 0000000000..63a239c396 --- /dev/null +++ b/site/docs/encoding/bandPosition.md @@ -0,0 +1,31 @@ +--- +layout: docs +title: Band Position +permalink: /docs/bandposition.html +--- + +Band properties can be used to adjust mark bandwidth or position for band scales, bin intervals, or time unit intervals. + +{% include table.html props="bandPosition" source="DatumDef" %} + +## Examples + +### Line Position + +By default, points in line marks are placed at the beginning of a time interval (e.g., "month"): + + + +Setting `bandPosition` to `0.5` moves the points to the middle of the time interval. + + + +### Bar Position + +By default, bar marks are placed from the beginning of a time interval (e.g., "month") to the end of the interval: + + + +Setting `bandPosition` to `0` moves the bar to center-align with ticks. + + diff --git a/site/docs/transform/timeunit.md b/site/docs/transform/timeunit.md index 7f6ef48e6b..1074cd956e 100644 --- a/site/docs/transform/timeunit.md +++ b/site/docs/transform/timeunit.md @@ -68,6 +68,12 @@ Using `timeUnit` with rect-based marks (including `bar`, `rect`, and `image`) wi You can also add `"binned"` prefix if your data has already been binned and want Vega-Lite to apply the right formatting, including the right bands for the interval, to your charts. +By default, bar marks are placed from the beginning of a time interval (e.g., "month") to the end of the interval. + +Setting [`bandPosition`](bandposition.html) to `0` moves the bar to center-align with ticks. + + + ### Time Unit's Band diff --git a/src/channeldef.ts b/src/channeldef.ts index 77ed5a2581..7f2ccb8eb7 100644 --- a/src/channeldef.ts +++ b/src/channeldef.ts @@ -534,7 +534,7 @@ export function getBandPosition({ if (isFieldDef(fieldDef)) { const {timeUnit, bin} = fieldDef; if (timeUnit && !fieldDef2) { - return isRectBasedMark(mark.type) ? 0 : getMarkConfig('timeUnitBandPosition', mark, config); + return getMarkConfig('timeUnitBandPosition', mark, config); } else if (isBinning(bin)) { return 0.5; } diff --git a/src/compile/data/aggregate.ts b/src/compile/data/aggregate.ts index b09238cf78..a8a9cefba1 100644 --- a/src/compile/data/aggregate.ts +++ b/src/compile/data/aggregate.ts @@ -5,9 +5,18 @@ import { getPositionChannelFromLatLong, getSecondaryRangeChannel, isGeoPositionChannel, - isScaleChannel + isScaleChannel, + isXorY } from '../../channel'; -import {binRequiresRange, FieldDef, hasBandEnd, isScaleFieldDef, isTypedFieldDef, vgField} from '../../channeldef'; +import { + binRequiresRange, + FieldDef, + getBandPosition, + hasBandEnd, + isScaleFieldDef, + isTypedFieldDef, + vgField +} from '../../channeldef'; import * as log from '../../log'; import {isFieldRange} from '../../scale'; import {AggregateTransform} from '../../transform'; @@ -15,6 +24,8 @@ import {Dict, duplicate, hash, keys, replacePathInField, setEqual} from '../../u import {isUnitModel, ModelWithField} from '../model'; import {UnitModel} from '../unit'; import {DataFlowNode} from './dataflow'; +import {isRectBasedMark} from '../../mark'; +import {OFFSETTED_RECT_END_SUFFIX, OFFSETTED_RECT_START_SUFFIX} from './timeunit'; type Measures = Dict