Skip to content

Commit

Permalink
fix: Remove x2/y2 channels for overlaying line and point (#8472)
Browse files Browse the repository at this point in the history
* add example

* Remove y2/x2 channel for overlaying lines and points

* Add comment
  • Loading branch information
yhoonkim committed Oct 12, 2022
1 parent 93b4585 commit 43d3dee
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 0 deletions.
Binary file added examples/compiled/area_overlay_with_y2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/compiled/area_overlay_with_y2.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
166 changes: 166 additions & 0 deletions examples/compiled/area_overlay_with_y2.vg.json
@@ -0,0 +1,166 @@
{
"$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'"}]
},
{
"name": "data_0",
"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": "area",
"style": ["area"],
"sort": {"field": "datum[\"date\"]"},
"from": {"data": "source_0"},
"encode": {
"update": {
"opacity": {"value": 0.7},
"orient": {"value": "vertical"},
"fill": {"value": "#4c78a8"},
"description": {
"signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))"
},
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "price"},
"y2": {"scale": "y", "value": 0},
"defined": {
"signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])"
}
}
}
},
{
"name": "layer_1_marks",
"type": "line",
"style": ["line"],
"sort": {"field": "datum[\"date\"]"},
"from": {"data": "source_0"},
"encode": {
"update": {
"stroke": {"value": "#4c78a8"},
"description": {
"signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))"
},
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "price"},
"defined": {
"signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])"
}
}
}
},
{
"name": "layer_2_marks",
"type": "symbol",
"style": ["point"],
"from": {"data": "data_0"},
"encode": {
"update": {
"opacity": {"value": 1},
"fill": {"value": "#4c78a8"},
"ariaRoleDescription": {"value": "point"},
"description": {
"signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))"
},
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "price"}
}
}
}
],
"scales": [
{
"name": "x",
"type": "time",
"domain": {
"fields": [
{"data": "source_0", "field": "date"},
{"data": "data_0", "field": "date"}
]
},
"range": [0, {"signal": "width"}]
},
{
"name": "y",
"type": "linear",
"domain": {
"fields": [
{"data": "source_0", "field": "price"},
[0],
{"data": "data_0", "field": "price"}
]
},
"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": "date",
"labelFlush": true,
"labelOverlap": true,
"tickCount": {"signal": "ceil(width/40)"},
"zindex": 0
},
{
"scale": "y",
"orient": "left",
"grid": false,
"title": "price",
"labelOverlap": true,
"tickCount": {"signal": "ceil(height/40)"},
"zindex": 0
}
]
}
12 changes: 12 additions & 0 deletions examples/specs/area_overlay_with_y2.vl.json
@@ -0,0 +1,12 @@
{
"$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'"}],
"mark": {"type": "area", "line": true, "point": true},
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"},
"y2": {"datum": 0, "type": "quantitative"}
}
}
30 changes: 30 additions & 0 deletions examples/specs/normalized/area_overlay_with_y2_normalized.vl.json
@@ -0,0 +1,30 @@
{
"$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'"}],
"layer": [
{
"mark": {"opacity": 0.7, "type": "area"},
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"},
"y2": {"datum": 0, "type": "quantitative"}
}
},
{
"mark": {"type": "line"},
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
},
{
"mark": {"type": "point", "opacity": 1, "filled": true},
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
}
]
}
5 changes: 5 additions & 0 deletions src/normalize/pathoverlay.ts
Expand Up @@ -143,6 +143,11 @@ export class PathOverlayNormalizer implements NonFacetUnitNormalizer<UnitSpecWit
};
}

// overlay line layer should be on the edge of area but passing y2/x2 makes
// it as "rule" mark so that it draws unwanted vertical/horizontal lines.
// point overlay also should not have y2/x2 as it does not support.
overlayEncoding = omit(overlayEncoding, ['y2', 'x2']);

if (lineOverlay) {
layer.push({
...(projection ? {projection} : {}),
Expand Down
42 changes: 42 additions & 0 deletions test/normalize/pathoverlay.test.ts
Expand Up @@ -185,6 +185,48 @@ describe('PathOverlayNormalizer', () => {
});
});

it('correctly normalizes area using y2 with overlay line.', () => {
const spec: TopLevelSpec = {
data: {url: 'data/stocks.csv'},
mark: 'area',
encoding: {
x: {field: 'date', type: 'temporal'},
y: {field: 'price', type: 'quantitative'},
y2: {value: 0, type: 'quantitative'}
},
config: {area: {line: {}, point: {}}}
};
const normalizedSpec = normalize(spec);
expect(normalizedSpec).toEqual({
data: {url: 'data/stocks.csv'},
layer: [
{
mark: {type: 'area', opacity: 0.7},
encoding: {
x: {field: 'date', type: 'temporal'},
y: {field: 'price', type: 'quantitative'},
y2: {value: 0, type: 'quantitative'}
}
},
{
mark: {type: 'line'},
encoding: {
x: {field: 'date', type: 'temporal'},
y: {field: 'price', type: 'quantitative', stack: 'zero'}
}
},
{
mark: {type: 'point', opacity: 1, filled: true},
encoding: {
x: {field: 'date', type: 'temporal'},
y: {field: 'price', type: 'quantitative', stack: 'zero'}
}
}
],
config: {area: {line: {}, point: {}}}
});
});

it('correctly normalizes interpolated area with overlay line', () => {
const spec: TopLevelSpec = {
data: {url: 'data/stocks.csv'},
Expand Down

0 comments on commit 43d3dee

Please sign in to comment.