To support selection, I propose the following syntax:
<script>
import { Graphic, Section, Point, Rectangle } from '@snlab/florence'
const pointData = [ ... ]
const selectedPoints = {}
let section
let selectRectangle
const initSelection = event => {
section.resetSelection()
const { x, y } = event.screenCoordinates
selectRectangle = { x1: x, x2: x, y1: y, y2: y }
}
const updateSelection = event => {
const { x, y } = event.screenCoordinates
selectRectangle.x2 = x
selectRectangle.y2 = y
section.updateSelection(selectRectangle)
}
</script>
<Graphic width={500} height={500}>
<Section
bind:this={section}
onMousedown={initSelection}
onDrag={updateSelection}
>
{#each pointData as point, i (i)}
<Point
x={point.x}
y={point.y}
onSelect={() => { selectedPoints[i] = true }}
onDeselect={() => { delete selectionPoints[i] }}
fill={selectedPoints[i] ? 'red' : 'black' }
/>
{/each}
</Section>
{#if selectRectangle !== undefined}
<Rectangle {...selectRectangle} fill="green" opacity={0.2} />
{/if}
</Graphic>
The advantages of this method over the old vue-gg syntax are:
- The user has more control over when the selection fires and when it is 'reset'. This makes it easier in the future to implement things like brushing.
- In this example I am using a selection-rectangle, but any sort of polygon would work with the same syntax.
- Selections can be triggered programmatically- so you can just call
section.updateSelection with your own rectangle or polygon. This way you can, for example, create a map with points and polygons and easily light up all points that are in a polygon without using any of the mouse interactions.
- The
initSelection and updateSelection functions could be abstracted away and made customizable with helpers functions similar to createZoomHandler and createPanHandler.
The downside is that this is maybe a bit more boilerplate-y.
Some more ideas:
- In
vue-gg, the callbacks given to onSelect and onDeselect were fired when the Mark's centroid would be within the selection rectangle/polygon. However, in some cases it might be preferable to fire when the selection rectangle/polygon intersects the mark instead. I suggest we add a prop on the mark/layer saying selectionFires="intersectsPolygon" or something like that, where the default would be selectionFires="centroidInPolygon".
- We have to think about supporting this stuff for polar coordinates too. The implementation described here would be using screen coordinates, which would work in a polar coordinate system, but it would also be cool to be able to drag clockwise or counterclockwise in the polarcoordinate system and have a pie-slice-shaped selection polygon (if that makes any sense). I am not sure yet how we should implement that but I feel like there should be a way.
Thoughts?
To support selection, I propose the following syntax:
The advantages of this method over the old
vue-ggsyntax are:section.updateSelectionwith your own rectangle or polygon. This way you can, for example, create a map with points and polygons and easily light up all points that are in a polygon without using any of the mouse interactions.initSelectionandupdateSelectionfunctions could be abstracted away and made customizable with helpers functions similar tocreateZoomHandlerandcreatePanHandler.The downside is that this is maybe a bit more boilerplate-y.
Some more ideas:
vue-gg, the callbacks given toonSelectandonDeselectwere fired when the Mark's centroid would be within the selection rectangle/polygon. However, in some cases it might be preferable to fire when the selection rectangle/polygon intersects the mark instead. I suggest we add a prop on the mark/layer sayingselectionFires="intersectsPolygon"or something like that, where the default would beselectionFires="centroidInPolygon".Thoughts?