-
Notifications
You must be signed in to change notification settings - Fork 612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: enable interval
selections for cartographic projections
#6953
Conversation
36eafab
to
9679a96
Compare
2e870be
to
3a383f3
Compare
dec30fa
to
3002c88
Compare
src/compile/selection/assemble.ts
Outdated
const store: VgData = {name: selCmpt.name + STORE}; | ||
|
||
if (selCmpt.project.hasSelectionId) { | ||
store.transform = [{type: 'collect', sort: {field: SELECTION_ID}}]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arvind regarding #7932 and this PR I have a question:
- Is the transform for datum.values[0] missing here? because you mentioned that the transform for the lasso must include this formula to correctly work with 'vlSelectionTuples'
"transform": [ {"type": "formula", "expr": "datum.values[0]", "as": "_vgsid_"}, {"type": "collect", "sort": {"field": "_vgsid_"}} ]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good eye! In #7933 and vega/vega#3397 (both of which this PR depends on), I introduced a more optimized format for selection stores when only the SELECTION_ID
is being stored. In particular, after those two PRs, the selection store holds tuples in the form {_vgsid_, unit}
sorted by _vgsid_
. This structure allows us to skip the formula
transform, as well all the array generation that would previously happen for the fields
and values
keys of the older tuples. The {unit, fields, values}
tuple format still applied for non-selectionID based stores.
Hope that helps!
923b0e3
to
7254d28
Compare
other models as geoshapes are likely to be background layer.
…ransparent fill to capture events
4f191c4
to
045358c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have some questions from a first skim. Will look more and add more comments.
// Proxy scale reactions to ensure that an infinite loop doesn't occur | ||
// when an interval selection filter touches the scale. | ||
if (!scales.defined(selCmpt)) { | ||
const triggerSg = name + SCALE_TRIGGER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is Sg
short for? Please use full name if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short for signal. This is a convention used throughout src/compile/selection/
code. Do you want me to update this PR to fix it everywhere, send a separate PR, or keep it as is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping as is is fine but let's update to triggerSignal
in a follow up pull request. sg could be misinterpreted as scenegraph.
const triggerSg = name + SCALE_TRIGGER; | ||
const scaleTriggers = channels.map(proj => { | ||
const channel = proj.channel as 'x' | 'y'; | ||
const {data: dname, visual: vname} = proj.signals; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does visual become vname
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted the variable name to clearly indicate that it was referencing the name of the visual signal.
@@ -52,9 +52,10 @@ export function parseUnitSelection(model: UnitModel, selDefs: SelectionParameter | |||
events: isString(defaults.on) ? parseSelector(defaults.on, 'scope') : array(duplicate(defaults.on)) | |||
} as any); | |||
|
|||
const def_ = duplicate(def); // defensive copy to prevent compilers from causing side effects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Optional)
Do we need this because existing code caused side effects or because this PR introduces side effect?
If the latter, I'd prefer that we don't do this defensive copy, which seems alarming to me.
That said, if it's a lot of refactor to take this out, we can ignore this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this PR introduces side effects — namely, if the interval selection parser detects a map projection, it rewrites the defaults from x/y
projection to instead lat/lon
and updates the predicate field to SELECTION_ID
ready for subsequent selection parsers to operate. This was the cleanest, most scoped/localized way I could think of to introduce brushing on maps without triggering a more massive refactor since the rest of the interval selection components expect standard cartesian coordinate systems. So my preference would be to keep the defensive copy since its occurring just on the selection definitions.
@@ -281,7 +281,7 @@ export class UnitModel extends ModelWithField { | |||
if (this.encoding.x || this.encoding.y) { | |||
return 'cell'; | |||
} else { | |||
return undefined; | |||
return 'view'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reasons why we're adding view
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to page this in since it's been a while but I believe it's to force a transparent background to be able to capture events. Without a 'view'
style, there is no background specified on the overall view and so brushes only trigger if someone mouses down on a mark.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, vega/vega#3480
import {UnitModel} from '../unit'; | ||
import {assembleInit} from './assemble'; | ||
import {SelectionProjection, TUPLE_FIELDS} from './project'; | ||
import scales from './scales'; | ||
|
||
export const BRUSH = '_brush'; | ||
export const SCALE_TRIGGER = '_scale_trigger'; | ||
export const GEO_INIT_TICK = 'geo_interval_init_tick'; // Workaround for https://github.com/vega/vega/issues/3481 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add something to the issue about how we need to update Vega-Lite when the issue is fixed in Vega?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. Very exciting change!
🎉 |
Chained to #7933.
📦 Published PR as canary version:
5.2.1--canary.6953.50ab21f.0
✨ Test out this PR locally via:
npm install vega-lite@5.2.1--canary.6953.50ab21f.0 # or yarn add vega-lite@5.2.1--canary.6953.50ab21f.0