-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Control scroll zoom and add gesture handler warning #10962
Conversation
…o add in later if makes sense
…el event if scroll zoom control is on
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.
Just some thoughts and feedback after a read-through, though I'm glad to discuss in more detail!
debug/zoom_control.html
Outdated
zoom: 12.5, | ||
center: [-77.01866, 38.888], | ||
style: 'mapbox://styles/mapbox/streets-v10', | ||
scrollZoom: {controlled: true} |
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 do you think about requireCtrl
? My only concern with the word controlled
is that it has React connotations ("controlled components") which might suggest this has something to do with externally controlling zoom input rather than how it interacts with keyboard events.
src/ui/handler/scroll_zoom.js
Outdated
@@ -154,6 +168,10 @@ class ScrollZoomHandler { | |||
|
|||
wheel(e: WheelEvent) { | |||
if (!this.isEnabled()) return; | |||
if (this.isControlled() && !e.ctrlKey && !e.metaKey) { | |||
const scrollZoomControl = new mapboxgl.ScrollZoomControl({closeButton: false}).setHTML(); |
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.
A quick search for addControl suggests that AttributionControl
is the only control automatically added to the map. Do you think this is best as an opt-in control the developer must add or as an opt-out control you'd have to remove?
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.
+1 to this, I think its better to have an opt-in Control for this and not clutter the Map constructor params more. So it might be nice to add this in like this
const map = new mapboxgl.Map({..});
map.addControl(new mapboxgl.ZoomBlockerControl({}));
The reason I think this would be more ergonomic is because it would be easier for users to customize it. With something like this.
const map = new mapboxgl.Map({..});
const zoomBlocker = new mapboxgl.ScrollBlockerControl({..})
.setHTML(`<b>whatever content the user wants</b>`);
map.addControl(zoomBlocker);
Then instead of having this logic here the blocking of the zoom event can be done in the onAdd
method of the control, this way the rest of the codebase is unaware of the blocker control running.
const that = this; | ||
|
||
if (this.options.closeFadeOut) { | ||
setTimeout(() => { |
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 we use CSS transitions to avoid a timing loop, e.g.:
...-container {
opacity: 1;
transition: opacity 300ms ease-in-out;
}
and then either set the opacity directly or toggle a class as needed? (I don't think we have to worry about transitionend
events since nothing happens at the end of the transition.)
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.
thanks for starting this, this has been such a heavily requested feature and will be great addition.
My main suggestion is to go with making it opt-in and, trying to make the rest of the codebase unaware of it.
src/ui/handler/scroll_zoom.js
Outdated
@@ -154,6 +168,10 @@ class ScrollZoomHandler { | |||
|
|||
wheel(e: WheelEvent) { | |||
if (!this.isEnabled()) return; | |||
if (this.isControlled() && !e.ctrlKey && !e.metaKey) { | |||
const scrollZoomControl = new mapboxgl.ScrollZoomControl({closeButton: false}).setHTML(); |
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.
+1 to this, I think its better to have an opt-in Control for this and not clutter the Map constructor params more. So it might be nice to add this in like this
const map = new mapboxgl.Map({..});
map.addControl(new mapboxgl.ZoomBlockerControl({}));
The reason I think this would be more ergonomic is because it would be easier for users to customize it. With something like this.
const map = new mapboxgl.Map({..});
const zoomBlocker = new mapboxgl.ScrollBlockerControl({..})
.setHTML(`<b>whatever content the user wants</b>`);
map.addControl(zoomBlocker);
Then instead of having this logic here the blocking of the zoom event can be done in the onAdd
method of the control, this way the rest of the codebase is unaware of the blocker control running.
* .setHTML("<h1>'Use ⌘ + scroll to zoom the map'</h1>") | ||
* .addTo(map); | ||
*/ | ||
export default class ScrollZoomControl extends Evented { |
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.
Maybe a better name would be ScrollZoomBlockerControl
?
…ntrol.js, flow not working with event
… transition is flickering
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.
This is looking good. I had a few nits on the code, but I'm seeing some unexpected behavior when I use the debug page. I know this is a draft so apologies if you're already addressing these, but here's what I've noticed.
- The text flickers just before the control fades out.
- If you hold down CMD and really zoom in/out then let go of CMD, the warning pops up and the zoom ends. We should ensure that this control is deactivated for the length of the "zoom event", including inertia. There's no
wheelend
event or anything like that, but it looks like thescroll_zoom
handler has some similar logic to handle successive events as a single "event".
* new mapboxgl.ScrollZoomControl().setHTML(); | ||
* map.addControl(scrollZoomControl); |
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.
Nit: should be const scrollZoomControl = new mapbox...
…due to interference with fullscreen control
@ryanhamley Ah, thanks for clarifying - I can see the bug now. In response to letting zoom happen while the warning is displayed, I have a new change (haven't pushed it yet) that shortens the time of the warning and the fade happens more quickly, so I think it'll be less in the way / make more sense to allow for zoom with CMD or CTRL while the warning is displayed. |
… other operating systems for corresponding alert
display: flex; | ||
align-items: center; | ||
width: 100%; | ||
height: 100%; |
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.
is height: 100%
100% of the height or is it 100% of the width? I thought it meant 100% of the width (even though it's the height property) and that you have to do bottom: 0
to get full height. Though maybe because it's absolute positioned, this does work.
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.
Ah I did not know this, I originally had top: 0; left: 0; bottom: 0; right: 0; but based on a preliminary search it seems documented that height: 100% is 100% of the parent element height?
…mediately remove alert with ctrl/cmd key
…or what the method does
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.
The behavior itself looks great and it's awesome that it's finally being addressed, but it seems like @arindam1993's suggestion to make this a Control had an unintended consequence of introducing more complexity that it could have if it were a scrollZoom handler option (as proposed e.g. in #10614):
- It has to adhere to the Control interface, which relies on configurable corner positions, and for this PR led to creating a separate
full-container
position available for controls which feels like an awkward exception. - It adds the expectation of being highly configurable, with methods like
add/remove/toggleClassName
,setHTML
with sanitization, etc., where this narrow interaction use case doesn't really require that flexibility.
So in the end it feels like there's more code in this PR than the use case needs. Personally I would prefer a more minimalistic approach, where:
- There's just one unique class for the overlay without need to change it. Users will be able to use it for styling.
- There's just one text for it defined in
default_locale.js
with the ability to change it vialocale
option like other labels. - There's only
Ctrl
for the behavior (notCmd
) so there's no need to use different labels for Mac and others, becauseCtrl
is universal. - Fade out delay and duration and whether the overlay is even visible can be fully controlled through CSS without any JS options.
This may feel like nitpicking, but it's hard to remove code like this once it's added, and configurability is overrated for "reasonable defaults" features like this, so I always try to minimize the amount of code where possible for new features.
Closing this PR as #11029 is the preferred approach and has been merged into main. |
Closes #10227.
In order to address the issue of incidentally zooming the map instead of scrolling the page, this PR introduces a new feature that allows for scroll-zoom control, by requiring pressing either CMD or CTRL key while scrolling in order to zoom. There is also an alert (that can be opted on of) that appears when scrolling over the map without pressing CMD or CTRL key. This feature has been implemented as a control that can be added on. With this control implemented, you can still zoom with pinching.
There is also an option to set HTML or text in the warning. There is also an option to add new CSS classes to allow for some customization. If the alert HTML is not set by the client, the default alert will be "⌘ + scroll to zoom the map" (for MacOS) or "CTRL + scroll to zoom the map".
Check out the debug page: zoom_control.html which is also accessible as a manual testing page.
You can add the control to the map like so:
Here is a screen recording of the feature:
Screen.Recording.2021-09-10.at.9.56.02.AM.mov
Launch Checklist
@mapbox/map-design-team
@mapbox/static-apis
if this PR includes style spec API or visual changesmapbox-gl-js
changelog:<changelog></changelog>