Skip to content
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

[Interactivity] Selection #107

Open
luucvanderzee opened this issue Sep 16, 2019 · 2 comments · Fixed by #112
Open

[Interactivity] Selection #107

luucvanderzee opened this issue Sep 16, 2019 · 2 comments · Fixed by #112
Labels
enhancement New feature or request interactivity Related to interactivity

Comments

@luucvanderzee
Copy link
Collaborator

luucvanderzee commented Sep 16, 2019

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:

  1. 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.
  2. In this example I am using a selection-rectangle, but any sort of polygon would work with the same syntax.
  3. 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.
  4. 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:

  1. 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".
  2. 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?

@luucvanderzee luucvanderzee added enhancement New feature or request interactivity Related to interactivity labels Sep 16, 2019
@atepoorthuis
Copy link
Contributor

3x yes! This is a quite neat and clean. I agree with pretty much all your points here (and love the extensibility to 'lasso' type selection - and you can easily extend too to enable snapping for example in the handler function).

On when a selection is an actual selection: I agree and this links potentially to other interaction too where we might want to do 'click with buffer' type of things. In other words, it'd be nice if we can make the spatial relation between the exact point of the interaction and the Mark a bit more flexible.

@johsi-k
Copy link
Contributor

johsi-k commented Nov 21, 2019

As I was adding selection to the area mark it occurred to me that firing on centroid detection might not be the most intuitive approach. It could also be problematic in the case of concave shapes where the centroid might end up outside the shape boundary.

When it comes to how much of the shape should be contained within the selector, most CAD programs use an all-or-nothing approach and fire only if the selector encompasses the entire shape. Firing on intersection is distinguished by direction:

  • rectangular left-to-right drag/lasso clockwise drag for window selection (containment)
  • rectangular right-to-left drag/lasso anti-clockwise drag for crossing selection (intersection)

See for example https://youtu.be/OLsstz6AvlI?t=65

@johsi-k johsi-k reopened this Nov 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request interactivity Related to interactivity
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants