fleaflet / flutter_map

A versatile mapping package for Flutter. Simple and easy to learn, yet completely customizable and configurable, it's the best choice for mapping in your Flutter app.
https://pub.dev/packages/flutter_map
BSD 3-Clause "New" or "Revised" License
2.68k stars 848 forks source link

[SPEC] gesture system enhancements #1748

Open josxha opened 7 months ago

josxha commented 7 months ago

Motivation

The user experience can be smoothend if we add zoom level transitions and animation while and after zooming.

Open for comments. It needs to be decided what should get added and what shouldn't or only optionally.

Potential features

  1. Use transparency to blend between zoom levels while zooming
    • Leaflet and the legacy Google raster map use this.
    • The vector map by google does not uses zoom layer blending.
  2. Animated zooming when using the scroll wheel
  3. Option to animate to a full zoom level after gesture input stops, not active by default.
    • GoogleMaps raster tiles are animating to the next full zoom level in the same direction.
    • Leaflet seems to animate to the nearest full zoom level
  4. Use canvas rather than widgets for tiles.
    • GoogleMaps prefered to for better control over the performance.
    • This might have different results with flutter.
  5. Don't request tiles if a zoom level gets skipped when the user zooms fast.
    • This gets calculated by the excepted time a zoom level will be visible according to the zoom speed.
    • Don't show downscaled tiles with a zoom level difference >1. (map would look cluttered, large amount of tiles to draw hurts performance)
  6. Preloading of tiles at surrounding zoom levels
    • Ensures a more smooth transition
    • Greater data consumption
  7. https://github.com/fleaflet/flutter_map/issues/1768
  8. https://github.com/fleaflet/flutter_map/issues/1432
  9. Animate the rotation of the the ctrl key + click gesture. (ref https://github.com/fleaflet/flutter_map/pull/1809)

Scope for flutter_map

ID Feature Default behaviour Optional Requirements & additional information
1 Use transparency to blend between zoom levels while zooming
2 Animated zooming when using the scroll wheel
3 Animate to a full zoom level after pinch gesture ends
5 Don't request tiles if a zoom level gets skipped when the user zooms fast only when not noticable
6 Preloading of tiles at surrounding zoom levels to ensure a smooth transition ensure that succounding tiles begin to load after the visible tiles are finished
7 More natural fling animation logic
8 Add the twoFingerTapZoomOut gesture
9 Animate the keyTriggerClickRotate gesture

Resources

JaffaKetchup commented 7 months ago

Animate to a full zoom level after gesture input stops.

I think this should be optional - it's an advantage over leaflet that we support fractional zoom levels.

Don't request tiles if a zoom level gets skipped when the user zooms fast

I think this will be difficult to do well, without introducing a potentially noticeable delay for the user. The CancellableNetworkTileProvider already takes care of this by cancelling tiles that are disposed quickly after load.


One thing to potentially add is the preloading of tiles at surrounding zoom levels to ensure a smooth transition.

josxha commented 7 months ago

I think this should be optional - it's an advantage over leaflet that we support fractional zoom levels.

Yes, I agree.

I think this will be difficult to do well, without introducing a potentially noticeable delay for the user. The CancellableNetworkTileProvider already takes care of this by cancelling tiles that are disposed quickly after load.

I think it shouldn't be noticable as long as we tweak it correctly. It would then only hit on very fast zooming. edit: this could be a potential solution to https://github.com/fleaflet/flutter_map/issues/1602 too.

Added tile preloading to the list 👍🏼

JaffaKetchup commented 7 months ago

Oh, and also animated zooming with a scroll wheel would be great, but that might already be in your plans as part of Gestures. I've tried fiddling around with it a bit - getting it right is very hard, because it is very jerky if you restart the animation on every notch. The implementation behind https://github.com/flutter/flutter/pull/139392 might be of use (particularly https://github.com/Piinks/flutter/blob/8c4a69ad818a405087522f904d4560cd1152f56f/packages/flutter/lib/src/widgets/scroll_position_with_single_context.dart#L255-L291).

josxha commented 7 months ago

Oh, and also animated zooming with a scroll wheel would be great, but that might already be in your plans as part of Gestures.

Added it to the list. I won't add it to https://github.com/fleaflet/flutter_map/pull/1733 but it's a nice addition as a follow up.

JosefWN commented 5 months ago

Minor (macOS/iOS): Essentially the opposite of https://github.com/fleaflet/flutter_map/issues/1768 (web).

A small flick in Apple Maps moves the map (animated pan) about ~25 mm on screen, a small flick in flutter_map makes the map jump ~5 mm instantly (from what I can tell, eyeballing). So it feels slightly unnatural, almost as if the map is resting on a table with a lot of friction.

JaffaKetchup commented 5 months ago

Ah, I wonder if FM feels so frictiony, at least in comparison to Google Maps because GM's 'friction' changes dependent on the cursor's distance from the equator. On the equator, the dragged point stays beneath the cursor the entire way, but on more extreme latitudes, the initially dragged point lags significantly behind the cursor.

a small flick in flutter_map makes the map jump ~5 mm instantly (from what I can tell, eyeballing)

I'm assuming you mean with the fling animation disabled?

JosefWN commented 5 months ago

I'm assuming you mean with the fling animation disabled?

With the fling animation enabled, that's why it feels a bit off for lighter flicks on the touch pad (very small instant movement, no animation that I can perceive).

mootw commented 4 days ago

Considerations:

I recently found trouble when trying to capture pan events. I needed to capture horizontalDrag and verticalDrag separately rather than what i would intuitively think would be a pan in GestureDetector with AbsorbPointer

Also i noticed that gesture detector has support for mapping scroll events to scale events (scale = zoom in flutter gestures). I wonder if we can tap into that to integrate closer to how flutter handles gestures.

Gesture Detector 'mapping' to our terminology: Scale would be zooming and rotation using a pinch gesture. pan would be a single finger drag (tap is tap... long... etc..)

josxha commented 3 days ago

I recently found trouble when trying to capture pan events. I needed to capture horizontalDrag and verticalDrag separately rather than what i would intuitively think would be a pan in GestureDetector with AbsorbPointer

There is an open issue here: https://github.com/fleaflet/flutter_map/issues/1729

Gesture Detector 'mapping' to our terminology: Scale would be zooming and rotation using a pinch gesture. pan would be a single finger drag (tap is tap... long... etc..)

I tried to follow this approach in https://github.com/fleaflet/flutter_map/pull/1809. The pr uses the scale callbacks but doesn't use pinch at the moment. There was some incompatibility between some GestureDetector callbacks. Could be that that's the reason it isn't used but I'm not sure.