Reputation: 3764
I have two area charts arranged vertically (adapted from this example). Brushing the bottom (overview) area zooms the top (detail) area. Another brush has been added to the top area. In this example, April-July has been brushed in the top chart.
When panning the top area with the bottom brush (indicated by red arrow below), the top brush stays put while the top area pans around. The intended behaviour is that the top brush would pan together with the top area (i.e. it would pan to the region marked with dashes and stay covering April-July).
How can the top brush pan together with the top area?
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Area charts of stock prices, with an interactive overview and filtered detail views.",
"width": 720,
"height": 480,
"padding": 5,
"data": [
{
"name": "sp500",
"url": "data/sp500.csv",
"format": {"type": "csv", "parse": {"price": "number", "date": "date"}}
}
],
"signals": [{"name": "detailDomain"}, {"name": "anotherDomain"}],
"marks": [
{
"type": "group",
"name": "detail",
"encode": {"enter": {"height": {"value": 390}, "width": {"value": 720}}},
"scales": [
{
"name": "xDetail",
"type": "time",
"range": "width",
"domain": {"data": "sp500", "field": "date"},
"domainRaw": {"signal": "detailDomain"}
},
{
"name": "yDetail",
"type": "linear",
"range": [390, 0],
"domain": {"data": "sp500", "field": "price"},
"nice": true,
"zero": true
}
],
"axes": [
{"orient": "bottom", "scale": "xDetail"},
{"orient": "left", "scale": "yDetail"}
],
"marks": [
{
"name": "detail",
"type": "group",
"encode": {
"enter": {
"height": {"field": {"group": "height"}},
"width": {"field": {"group": "width"}},
"clip": {"value": true},
"fill": {"value": "transparent"}
}
},
"signals": [
{
"name": "brush",
"value": 0,
"on": [
{"events": "@detail:pointerdown", "update": "[x(), x()]"},
{
"events": "[@detail:pointerdown, window:pointerup] > window:pointermove!",
"update": "[brush[0], clamp(x(), 0, width)]"
},
{
"events": {"signal": "delta"},
"update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
}
]
},
{
"name": "anchor",
"value": null,
"on": [{"events": "@brush:pointerdown", "update": "slice(brush)"}]
},
{
"name": "xdown",
"value": 0,
"on": [{"events": "@brush:pointerdown", "update": "x()"}]
},
{
"name": "delta",
"value": 0,
"on": [
{
"events": "[@brush:pointerdown, window:pointerup] > window:pointermove!",
"update": "x() - xdown"
}
]
},
{
"name": "anotherDomain",
"push": "outer",
"on": [
{
"events": {"signal": "brush"},
"update": "span(brush) ? invert('xDetail', brush) : null"
}
]
}
],
"marks": [
{
"type": "area",
"from": {"data": "sp500"},
"encode": {
"update": {
"x": {"scale": "xDetail", "field": "date"},
"y": {"scale": "yDetail", "field": "price"},
"y2": {"scale": "yDetail", "value": 0},
"fill": {"value": "steelblue"}
}
}
},
{
"type": "rect",
"name": "brush",
"encode": {
"enter": {
"y": {"value": 0},
"height": {"value": 390},
"fill": {"value": "#333"},
"fillOpacity": {"value": 0.2}
},
"update": {
"x": {"signal": "brush[0]"},
"x2": {"signal": "brush[1]"}
}
}
}
]
}
]
},
{
"type": "group",
"name": "overview",
"encode": {
"enter": {
"x": {"value": 0},
"y": {"value": 430},
"height": {"value": 70},
"width": {"value": 720},
"fill": {"value": "transparent"}
}
},
"signals": [
{
"name": "brush",
"value": 0,
"on": [
{"events": "@overview:pointerdown", "update": "[x(), x()]"},
{
"events": "[@overview:pointerdown, window:pointerup] > window:pointermove!",
"update": "[brush[0], clamp(x(), 0, width)]"
},
{
"events": {"signal": "delta"},
"update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
}
]
},
{
"name": "anchor",
"value": null,
"on": [{"events": "@brush:pointerdown", "update": "slice(brush)"}]
},
{
"name": "xdown",
"value": 0,
"on": [{"events": "@brush:pointerdown", "update": "x()"}]
},
{
"name": "delta",
"value": 0,
"on": [
{
"events": "[@brush:pointerdown, window:pointerup] > window:pointermove!",
"update": "x() - xdown"
}
]
},
{
"name": "detailDomain",
"push": "outer",
"on": [
{
"events": {"signal": "brush"},
"update": "span(brush) ? invert('xOverview', brush) : null"
}
]
}
],
"scales": [
{
"name": "xOverview",
"type": "time",
"range": "width",
"domain": {"data": "sp500", "field": "date"}
},
{
"name": "yOverview",
"type": "linear",
"range": [70, 0],
"domain": {"data": "sp500", "field": "price"},
"nice": true,
"zero": true
}
],
"axes": [{"orient": "bottom", "scale": "xOverview"}],
"marks": [
{
"type": "area",
"interactive": false,
"from": {"data": "sp500"},
"encode": {
"update": {
"x": {"scale": "xOverview", "field": "date"},
"y": {"scale": "yOverview", "field": "price"},
"y2": {"scale": "yOverview", "value": 0},
"fill": {"value": "steelblue"}
}
}
},
{
"type": "rect",
"name": "brush",
"encode": {
"enter": {
"y": {"value": 0},
"height": {"value": 70},
"fill": {"value": "#333"},
"fillOpacity": {"value": 0.2}
},
"update": {
"x": {"signal": "brush[0]"},
"x2": {"signal": "brush[1]"}
}
}
}
]
}
]
}
Upvotes: 1
Views: 28
Reputation: 30174
Try this. I also fixed the ability to drag over the area chart.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Area charts of stock prices, with an interactive overview and filtered detail views.",
"width": 720,
"height": 480,
"padding": 5,
"data": [
{
"name": "sp500",
"url": "data/sp500.csv",
"format": {"type": "csv", "parse": {"price": "number", "date": "date"}}
}
],
"signals": [
{"name": "detailDomain"},
{"name": "anotherDomain"},
{
"name": "brush",
"value": 0,
"on": [
{"events": "@detail:pointerdown", "update": "[x(), x()]"},
{
"events": "[@detail:pointerdown, window:pointerup] > window:pointermove!",
"update": "[brush[0], clamp(x(), 0, width)]"
},
{
"events": {"signal": "delta"},
"update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
}
]
},
{
"name": "anchor",
"value": null,
"on": [{"events": "@brush:pointerdown", "update": "slice(brush)"}]
},
{
"name": "xdown",
"value": 0,
"on": [{"events": "@brush:pointerdown", "update": "x()"}]
},
{
"name": "delta",
"value": 0,
"on": [
{
"events": "[@brush:pointerdown, window:pointerup] > window:pointermove!",
"update": "x() - xdown"
}
]
}
],
"marks": [
{
"type": "group",
"encode": {"enter": {"height": {"value": 390}, "width": {"value": 720}}},
"scales": [
{
"name": "xDetail",
"type": "time",
"range": "width",
"domain": {"data": "sp500", "field": "date"},
"domainRaw": {"signal": "detailDomain"}
},
{
"name": "yDetail",
"type": "linear",
"range": [390, 0],
"domain": {"data": "sp500", "field": "price"},
"nice": true,
"zero": true
}
],
"axes": [
{"orient": "bottom", "scale": "xDetail"},
{"orient": "left", "scale": "yDetail"}
],
"marks": [
{
"name": "detail",
"type": "group",
"encode": {
"enter": {
"height": {"field": {"group": "height"}},
"width": {"field": {"group": "width"}},
"clip": {"value": true},
"fill": {"value": "transparent"}
}
},
"signals": [
{
"name": "brush",
"value": 0,
"on": [
{"events": "@detail:pointerdown", "update": "[x(), x()]"},
{
"events": "[@detail:pointerdown, window:pointerup] > window:pointermove!",
"update": "[brush[0], clamp(x(), 0, width)]"
},
{
"events": {"signal": "delta"},
"update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
}
]
},
{
"name": "anchor",
"value": null,
"on": [{"events": "@brush:pointerdown", "update": "slice(brush)"}]
},
{
"name": "xdown",
"value": 0,
"on": [{"events": "@brush:pointerdown", "update": "x()"}]
},
{
"name": "delta",
"value": 0,
"on": [
{
"events": "[@brush:pointerdown, window:pointerup] > window:pointermove!",
"update": "x() - xdown"
}
]
},
{
"name": "anotherDomain",
"push": "outer",
"on": [
{
"events": {"signal": "brush"},
"update": "span(brush) ? invert('xDetail', brush) : null"
}
]
}
],
"marks": [
{
"type": "area",
"from": {"data": "sp500"},
"interactive": false,
"encode": {
"update": {
"x": {"scale": "xDetail", "field": "date"},
"y": {"scale": "yDetail", "field": "price"},
"y2": {"scale": "yDetail", "value": 0},
"fill": {"value": "steelblue"}
}
}
},
{
"type": "rect",
"name": "brush",
"encode": {
"enter": {
"y": {"value": 0},
"height": {"value": 390},
"fill": {"value": "#333"},
"fillOpacity": {"value": 0.2}
},
"update": {
"x": {"signal": "anotherDomain?scale('xDetail', anotherDomain[0]):brush[0]"},
"x2": {"signal": "anotherDomain?scale('xDetail', anotherDomain[1]):brush[1]"}
}
}
}
]
}
]
},
{
"type": "group",
"name": "overview",
"encode": {
"enter": {
"x": {"value": 0},
"y": {"value": 430},
"height": {"value": 70},
"width": {"value": 720},
"fill": {"value": "transparent"}
}
},
"signals": [
{
"name": "brush",
"value": 0,
"on": [
{"events": "@overview:pointerdown", "update": "[x(), x()]"},
{
"events": "[@overview:pointerdown, window:pointerup] > window:pointermove!",
"update": "[brush[0], clamp(x(), 0, width)]"
},
{
"events": {"signal": "delta"},
"update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
}
]
},
{
"name": "anchor",
"value": null,
"on": [{"events": "@brush:pointerdown", "update": "slice(brush)"}]
},
{
"name": "xdown",
"value": 0,
"on": [{"events": "@brush:pointerdown", "update": "x()"}]
},
{
"name": "delta",
"value": 0,
"on": [
{
"events": "[@brush:pointerdown, window:pointerup] > window:pointermove!",
"update": "x() - xdown"
}
]
},
{
"name": "detailDomain",
"push": "outer",
"on": [
{
"events": {"signal": "brush"},
"update": "span(brush) ? invert('xOverview', brush) : null"
}
]
}
],
"scales": [
{
"name": "xOverview",
"type": "time",
"range": "width",
"domain": {"data": "sp500", "field": "date"}
},
{
"name": "yOverview",
"type": "linear",
"range": [70, 0],
"domain": {"data": "sp500", "field": "price"},
"nice": true,
"zero": true
}
],
"axes": [{"orient": "bottom", "scale": "xOverview"}],
"marks": [
{
"type": "area",
"interactive": false,
"from": {"data": "sp500"},
"encode": {
"update": {
"x": {"scale": "xOverview", "field": "date"},
"y": {"scale": "yOverview", "field": "price"},
"y2": {"scale": "yOverview", "value": 0},
"fill": {"value": "steelblue"}
}
}
},
{
"type": "rect",
"name": "brush",
"encode": {
"enter": {
"y": {"value": 0},
"height": {"value": 70},
"fill": {"value": "#333"},
"fillOpacity": {"value": 0.2}
},
"update": {
"x": {"signal": "brush[0]"},
"x2": {"signal": "brush[1]"}
}
}
}
]
}
]
}
Upvotes: 1