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

Better support for finalising drawn shapes #314

Closed
aidanlister opened this issue May 26, 2016 · 12 comments
Closed

Better support for finalising drawn shapes #314

aidanlister opened this issue May 26, 2016 · 12 comments

Comments

@aidanlister
Copy link

My use case is the user creates a bounding box and I highlight all the markers within that bounding box.

The Google Maps API has a draw.end style event when the user double clicks, allowing me to change the color of the bounded area and move to the next step. This works quite well.

I haven't been able to do this as elegantly with draw.changed ... it fires in realtime as the user changes their shape so I either need to debounce it or try and add a "finished" button somewhere into the process.

What's the thinking on how this could be better supported?

@mcwhittemore
Copy link
Contributor

@aidanlister - just to make sure we're on the same page here. In your use case the user is drawing a polygon and you are using this polygon to highlight a bunch of points. Is that correct?

draw.changed gets emitted once per frame if something has changed. I don't think slowing this down inside of Draw is a good idea as it limits the speed someone could respond to changes. Playing around with your use case a bit it seems like debouncing is a great option. Why don't you want to do this?

Assuming there is a good reason debouncing doesn't work, there are a few other events that draw emits that help us guess at when someone is done editing. draw.modechanged fires when the behavior of Draw is changed. When going to simple_select from any other mode we can assume drawing has stopped. That said, editing can happen in both simple_select and direct_select. If unselecting the feature is a good enough measurement of the end of drawing than we can use the draw.mode.simple_select.selected.end event along with draw.modechanged to know when drawing has ended. This has problems though, ie: I don't want to unselect the feature but I'm done drawing. My guess is that some sort of debounce + the above solution could get you 90% of the way there.

This is a great idea and is a problem worth solving but the when is the user done drawing problem is not the aim of Draw. This kind of interaction detection is very complex. If you want to create module that does this and need Draw to emit some details it is not emitting currently please feel free to ask (or open a PR with your additions). Also, if you make a module that does this, please link drop it here so that going forward users don't feel the need to reimplement. In the future (I'd guess) there will be a handful of utility tools like this that we will want to promote.

Good luck!

@aidanlister
Copy link
Author

@mcwhittemore Yes that's right, here's a screenshot of the process in google maps: http://share.aidanlister.com/gHrz

I also sent you a link to the sandbox if you wanted to play with it, no worries if you don't have time.

I see what you're saying though ... the nature of the polygon tool in mapbox-gl-draw is quite different as it's immediately a valid shape from the first click. The google maps polygon tool is only valid once you've double clicked to complete the shape.

The modechanged sort of works but it's not clear to the user what the trigger points are (as you said, gets you 90% of the way). We've implemented the debouncing as an intermediary solution ... it's okay ... there's considerable jank every 500ms when we call Turf to do the calculation but it is what it is.

Is there any way I can hook into the line tool to make it behave the same way the google maps polygon tool does?

@bor3ham
Copy link

bor3ham commented May 27, 2016

+1

Also I noticed there's no way to finish the polygon without double clicking, however the double click is interpreted as zoom in addition to "finishing" the shape. This doesn't seem like the behaviour the user would expect.

@mcwhittemore
Copy link
Contributor

@aidanlister I'm getting a 403 with your demo page. That said, if all you care about is when a user is done drawing a polygon (editing isn't an option) the move from draw_polygon to simple_select indicates this. You can listen to draw.modechanged to detect this.

Also, there is some talk here about letting users implement their own modes. I don't have time to work on this, but if you want to make the PR that would be amazing.

@aidanlister
Copy link
Author

@mcwhittemore there's two issues I guess:

  1. The first is that to finish drawing a polygon and free the mouse pointer, you must double click. This emits a modechange (from draw_polygon) to simple_select which we could capture ... but it also zooms the map, which we don't want. Can we prevent the zooming?

  2. If they edit the shape, we can listen to a mode change (from *) to direct_select, and then debounce draw.changed to fire every 500ms or so. That's fine, but I'd rather disable that if possible?

@mcwhittemore
Copy link
Contributor

mcwhittemore commented Jun 2, 2016

Can we prevent the zooming?

Enter will also work. I think mapbox/mapbox-gl-js#2237 is blocking Draw's ability to turn off zoom, but this should be worked on.

If the debouncing is a frustration, can you just inform your users to unselect the feature and run the processing on the mode change back to simple_select? This still has problems as the feature can change in multi select.

@mcwhittemore
Copy link
Contributor

mcwhittemore commented Jun 8, 2016

I've been spending some time thinking about this today. Knowing when someone is done editing is hard, but knowing when they click is easy. We can use this to emit a less granular change.

We will want to make this change in /src/events.js

  • Add a draw.changed event handle to events.js
  • have the draw.changed event record all features that changed while the mouse is down
  • When the mouseup fires we need to use ctx.map.fire to emit a draw.modified event which should look like { features: [] } where the array is the most recent version of each feature caught via draw.changed.

@aidanlister
Copy link
Author

That sounds good (I assume mousedown/mouseup aren't the actual click and hold events they sound like, which the code seems to reflect)

@mcwhittemore
Copy link
Contributor

I assume mousedown/mouseup aren't the actual click and hold events they sound like,

@aidanlister I'm not sure what this means?

@aidanlister
Copy link
Author

mousedown sounds like click and hold, mouseup sounds like releasing that click. When drawing a shape you're not mousedown/mouseup, you're just clicking once ... but maybe I'm reading it wrong?

@mcwhittemore
Copy link
Contributor

@aidanlister gotcha. Click is down and up quickly. So in the draw modes you'd get a updated event with each new node rather than each time the mouse is moved.

@mcwhittemore
Copy link
Contributor

@aidanlister - 0.9.0 of Draw now has draw.modified. This event is much like draw.changed but is emitted much less frequently. I think this does a good job at solving the problem you raised here.

Closed by #358

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants