Skip to content

Commit

Permalink
feat: Region/Lasso Selections (#8988)
Browse files Browse the repository at this point in the history
* jfkj

* created new clean branch

* chore: update schema [CI]

* chore: update TOC [CI]

* refactored lasso to region, added runtime tests

* added examples

* linted region test

* chore: update schema [CI]

* chore: update examples [CI]

* updated example to fit v5

* chore: update examples [CI]

* readded filter and mark for example test

* chore: update examples [CI]

* deleted unused images, adjusted selection fields for documentation

* chore: update examples [CI]

* fix: hardwire SELECTION_ID as the only valid field for regions

* refactor: runtime tests to use hits object + regenerate resources

* fix: for global region selections, hide marks for inactive units

* test: expand runtime tests to cover faceted/repeated views

* chore: update examples [CI]

---------

Co-authored-by: Moritz Schöfl <moritz.schoefl@datavisyn.io>
Co-authored-by: GitHub Actions Bot <vega-actions-bot@users.noreply.github.com>
Co-authored-by: Moritz Heckmann <moritz.heckmann@datavisyn.io>
  • Loading branch information
4 people authored Jul 17, 2023
1 parent 4da46c3 commit 7d20575
Show file tree
Hide file tree
Showing 59 changed files with 1,255 additions and 21 deletions.
113 changes: 112 additions & 1 deletion build/vega-lite-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -20731,6 +20731,106 @@
},
"type": "object"
},
"RegionSelectionConfig": {
"additionalProperties": false,
"properties": {
"clear": {
"anyOf": [
{
"$ref": "#/definitions/Stream"
},
{
"type": "string"
},
{
"type": "boolean"
}
],
"description": "Clears the selection, emptying it of all values. This property can be a [Event Stream](https://vega.github.io/vega/docs/event-streams/) or `false` to disable clear.\n\n__Default value:__ `dblclick`.\n\n__See also:__ [`clear` examples ](https://vega.github.io/vega-lite/docs/selection.html#clear) in the documentation."
},
"encodings": {
"description": "An array of encoding channels. The corresponding data field values must match for a data tuple to fall within the selection.\n\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.",
"items": {
"$ref": "#/definitions/SingleDefUnitChannel"
},
"type": "array"
},
"mark": {
"$ref": "#/definitions/BrushConfig",
"description": "A region selection also adds a path mark to depict the shape of the region. The `mark` property can be used to customize the appearance of the mark.\n\n__See also:__ [`mark` examples](https://vega.github.io/vega-lite/docs/selection.html#mark) in the documentation."
},
"on": {
"anyOf": [
{
"$ref": "#/definitions/Stream"
},
{
"type": "string"
}
],
"description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or selector) that triggers the selection. For interval selections, the event stream must specify a [start and end](https://vega.github.io/vega/docs/event-streams/#between-filters).\n\n__See also:__ [`on` examples](https://vega.github.io/vega-lite/docs/selection.html#on) in the documentation."
},
"resolve": {
"$ref": "#/definitions/SelectionResolution",
"description": "With layered and multi-view displays, a strategy that determines how selections' data queries are resolved when applied in a filter transform, conditional encoding rule, or scale domain.\n\nOne of:\n- `\"global\"` -- only one brush exists for the entire SPLOM. When the user begins to drag, any previous brushes are cleared, and a new one is constructed.\n- `\"union\"` -- each cell contains its own brush, and points are highlighted if they lie within _any_ of these individual brushes.\n- `\"intersect\"` -- each cell contains its own brush, and points are highlighted only if they fall within _all_ of these individual brushes.\n\n__Default value:__ `global`.\n\n__See also:__ [`resolve` examples](https://vega.github.io/vega-lite/docs/selection.html#resolve) in the documentation."
},
"type": {
"const": "region",
"description": "Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`.",
"type": "string"
}
},
"required": [
"type"
],
"type": "object"
},
"RegionSelectionConfigWithoutType": {
"additionalProperties": false,
"properties": {
"clear": {
"anyOf": [
{
"$ref": "#/definitions/Stream"
},
{
"type": "string"
},
{
"type": "boolean"
}
],
"description": "Clears the selection, emptying it of all values. This property can be a [Event Stream](https://vega.github.io/vega/docs/event-streams/) or `false` to disable clear.\n\n__Default value:__ `dblclick`.\n\n__See also:__ [`clear` examples ](https://vega.github.io/vega-lite/docs/selection.html#clear) in the documentation."
},
"encodings": {
"description": "An array of encoding channels. The corresponding data field values must match for a data tuple to fall within the selection.\n\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.",
"items": {
"$ref": "#/definitions/SingleDefUnitChannel"
},
"type": "array"
},
"mark": {
"$ref": "#/definitions/BrushConfig",
"description": "A region selection also adds a path mark to depict the shape of the region. The `mark` property can be used to customize the appearance of the mark.\n\n__See also:__ [`mark` examples](https://vega.github.io/vega-lite/docs/selection.html#mark) in the documentation."
},
"on": {
"anyOf": [
{
"$ref": "#/definitions/Stream"
},
{
"type": "string"
}
],
"description": "A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or selector) that triggers the selection. For interval selections, the event stream must specify a [start and end](https://vega.github.io/vega/docs/event-streams/#between-filters).\n\n__See also:__ [`on` examples](https://vega.github.io/vega-lite/docs/selection.html#on) in the documentation."
},
"resolve": {
"$ref": "#/definitions/SelectionResolution",
"description": "With layered and multi-view displays, a strategy that determines how selections' data queries are resolved when applied in a filter transform, conditional encoding rule, or scale domain.\n\nOne of:\n- `\"global\"` -- only one brush exists for the entire SPLOM. When the user begins to drag, any previous brushes are cleared, and a new one is constructed.\n- `\"union\"` -- each cell contains its own brush, and points are highlighted if they lie within _any_ of these individual brushes.\n- `\"intersect\"` -- each cell contains its own brush, and points are highlighted only if they fall within _all_ of these individual brushes.\n\n__Default value:__ `global`.\n\n__See also:__ [`resolve` examples](https://vega.github.io/vega-lite/docs/selection.html#resolve) in the documentation."
}
},
"type": "object"
},
"RegressionTransform": {
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -21949,6 +22049,10 @@
"point": {
"$ref": "#/definitions/PointSelectionConfigWithoutType",
"description": "The default definition for a [`point`](https://vega.github.io/vega-lite/docs/parameter.html#select) selection. All properties and transformations for a point selection definition (except `type`) may be specified here.\n\nFor instance, setting `point` to `{\"on\": \"dblclick\"}` populates point selections on double-click by default."
},
"region": {
"$ref": "#/definitions/RegionSelectionConfigWithoutType",
"description": "The default definition for an [`region`](https://vega.github.io/vega-lite/docs/parameter.html#select) selection. All properties and transformations for an region selection definition (except `type`) may be specified here."
}
},
"type": "object"
Expand Down Expand Up @@ -22023,6 +22127,9 @@
},
{
"$ref": "#/definitions/IntervalSelectionConfig"
},
{
"$ref": "#/definitions/RegionSelectionConfig"
}
],
"description": "Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`."
Expand Down Expand Up @@ -22062,7 +22169,8 @@
"SelectionType": {
"enum": [
"point",
"interval"
"interval",
"region"
],
"type": "string"
},
Expand Down Expand Up @@ -29483,6 +29591,9 @@
},
{
"$ref": "#/definitions/IntervalSelectionConfig"
},
{
"$ref": "#/definitions/RegionSelectionConfig"
}
],
"description": "Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`."
Expand Down
Binary file added examples/compiled/selection_type_region.png
Loading
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/selection_type_region.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
220 changes: 220 additions & 0 deletions examples/compiled/selection_type_region.vg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"background": "white",
"padding": 5,
"width": 200,
"height": 200,
"style": "cell",
"data": [
{
"name": "brush_store",
"transform": [{"type": "collect", "sort": {"field": "_vgsid_"}}]
},
{
"name": "source_0",
"url": "data/cars.json",
"format": {"type": "json"},
"transform": [
{"type": "identifier", "as": "_vgsid_"},
{
"type": "filter",
"expr": "isValid(datum[\"Horsepower\"]) && isFinite(+datum[\"Horsepower\"]) && isValid(datum[\"Miles_per_Gallon\"]) && isFinite(+datum[\"Miles_per_Gallon\"])"
}
]
}
],
"signals": [
{
"name": "unit",
"value": {},
"on": [
{"events": "mousemove", "update": "isTuple(group()) ? group() : unit"}
]
},
{
"name": "brush",
"update": "vlSelectionResolve(\"brush_store\", \"union\")"
},
{
"name": "brush_tuple",
"on": [
{
"events": [{"signal": "brush_screen_path"}],
"update": "vlSelectionTuples(intersectLasso(\"marks\", brush_screen_path, unit), {unit: \"\"})"
},
{"events": [{"source": "view", "type": "dblclick"}], "update": "null"}
]
},
{
"name": "brush_screen_path",
"init": "[]",
"on": [
{
"events": {"source": "scope", "type": "mousedown"},
"update": "[[x(unit), y(unit)]]"
},
{
"events": {
"source": "window",
"type": "mousemove",
"consume": true,
"between": [
{"source": "scope", "type": "mousedown"},
{"source": "window", "type": "mouseup"}
]
},
"update": "lassoAppend(brush_screen_path, clamp(x(unit), 0, width), clamp(y(unit), 0, height))"
}
]
},
{
"name": "brush_modify",
"on": [
{
"events": {"signal": "brush_tuple"},
"update": "modify(\"brush_store\", brush_tuple, true)"
}
]
}
],
"marks": [
{
"name": "brush_brush",
"type": "path",
"encode": {
"enter": {
"fill": {"value": "#333"},
"fillOpacity": {"value": 0.125},
"stroke": {"value": "gray"},
"strokeWidth": {"value": 2},
"strokeDash": {"value": [8, 5]}
},
"update": {
"path": [
{
"test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"\"",
"signal": "lassoPath(brush_screen_path)"
},
{"value": "[]"}
]
}
}
},
{
"name": "marks",
"type": "symbol",
"style": ["point"],
"interactive": true,
"from": {"data": "source_0"},
"encode": {
"update": {
"opacity": {"value": 0.7},
"fill": {"value": "transparent"},
"stroke": [
{
"test": "!length(data(\"brush_store\")) || vlSelectionIdTest(\"brush_store\", datum)",
"scale": "color",
"field": "Cylinders"
},
{"value": "grey"}
],
"ariaRoleDescription": {"value": "point"},
"description": {
"signal": "\"Horsepower: \" + (format(datum[\"Horsepower\"], \"\")) + \"; Miles_per_Gallon: \" + (format(datum[\"Miles_per_Gallon\"], \"\")) + \"; Cylinders: \" + (isValid(datum[\"Cylinders\"]) ? datum[\"Cylinders\"] : \"\"+datum[\"Cylinders\"])"
},
"x": {"scale": "x", "field": "Horsepower"},
"y": {"scale": "y", "field": "Miles_per_Gallon"}
}
}
}
],
"scales": [
{
"name": "x",
"type": "linear",
"domain": {"data": "source_0", "field": "Horsepower"},
"range": [0, {"signal": "width"}],
"nice": true,
"zero": true
},
{
"name": "y",
"type": "linear",
"domain": {"data": "source_0", "field": "Miles_per_Gallon"},
"range": [{"signal": "height"}, 0],
"nice": true,
"zero": true
},
{
"name": "color",
"type": "ordinal",
"domain": {"data": "source_0", "field": "Cylinders", "sort": true},
"range": "ordinal",
"interpolate": "hcl"
}
],
"axes": [
{
"scale": "x",
"orient": "bottom",
"gridScale": "y",
"grid": true,
"tickCount": {"signal": "ceil(width/40)"},
"domain": false,
"labels": false,
"aria": false,
"maxExtent": 0,
"minExtent": 0,
"ticks": false,
"zindex": 0
},
{
"scale": "y",
"orient": "left",
"gridScale": "x",
"grid": true,
"tickCount": {"signal": "ceil(height/40)"},
"domain": false,
"labels": false,
"aria": false,
"maxExtent": 0,
"minExtent": 0,
"ticks": false,
"zindex": 0
},
{
"scale": "x",
"orient": "bottom",
"grid": false,
"title": "Horsepower",
"labelFlush": true,
"labelOverlap": true,
"tickCount": {"signal": "ceil(width/40)"},
"zindex": 0
},
{
"scale": "y",
"orient": "left",
"grid": false,
"title": "Miles_per_Gallon",
"labelOverlap": true,
"tickCount": {"signal": "ceil(height/40)"},
"zindex": 0
}
],
"legends": [
{
"stroke": "color",
"symbolType": "circle",
"title": "Cylinders",
"encode": {
"symbols": {
"update": {
"fill": {"value": "transparent"},
"opacity": {"value": 0.7}
}
}
}
}
]
}
Loading
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/selection_type_region_concat.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7d20575

Please sign in to comment.