Skip to content

Commit 7084a29

Browse files
committed
move two pointers vertically to pitch
1 parent fccf3f0 commit 7084a29

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

maplibre/lib/src/map_state.dart

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ abstract class MapLibreMapState extends State<MapLibreMap>
3737
vsync: this,
3838
duration: const Duration(milliseconds: 300),
3939
)..addListener(_onAnimation);
40+
final Map<int, Offset> _pointers = {};
4041
Animation<MapCamera>? _animation;
4142
ScaleStartDetails? _onScaleStartEvent;
4243
TapDownDetails? _doubleTapDownDetails;
@@ -54,8 +55,16 @@ abstract class MapLibreMapState extends State<MapLibreMap>
5455
child: Listener(
5556
onPointerDown: (event) {
5657
_pointerDownEvent = event;
58+
_pointers[event.pointer] = event.position;
5759
_stopAnimation();
5860
},
61+
onPointerMove: (event) {
62+
_pointers[event.pointer] = event.position;
63+
},
64+
onPointerUp: (event) {
65+
_pointers.remove(event.pointer);
66+
if (_pointers.isEmpty) _pointerDownEvent = null;
67+
},
5968
onPointerSignal: (event) {
6069
switch (event) {
6170
case final PointerScrollEvent event:
@@ -202,6 +211,7 @@ abstract class MapLibreMapState extends State<MapLibreMap>
202211
_lastScaleUpdateDetails = details;
203212
final ctrlPressed = HardwareKeyboard.instance.isControlPressed;
204213
final buttons = pointerDownEvent.buttons;
214+
final lastPointerOffset = lastEvent?.focalPoint ?? startEvent.focalPoint;
205215

206216
if (doubleTapDown != null && options.gestures.zoom) {
207217
// double tap drag: zoom
@@ -214,7 +224,6 @@ abstract class MapLibreMapState extends State<MapLibreMap>
214224
moveCamera(zoom: newZoom.clamp(options.minZoom, options.maxZoom));
215225
} else if ((buttons & kSecondaryMouseButton) != 0 || ctrlPressed) {
216226
// secondary button: pitch and bearing
217-
final lastPointerOffset = lastEvent?.focalPoint ?? startEvent.focalPoint;
218227
final delta = details.focalPoint - lastPointerOffset;
219228
var newBearing = camera.bearing;
220229
if (options.gestures.rotate) {
@@ -231,21 +240,25 @@ abstract class MapLibreMapState extends State<MapLibreMap>
231240
moveCamera(bearing: newBearing, pitch: newPitch, zoom: newZoom);
232241
} else if ((buttons & kPrimaryMouseButton) != 0) {
233242
// primary button: pan, zoom, bearing, pinch
243+
var pitch = false;
244+
if (options.gestures.pitch && _pointers.length == 2) {
245+
final pointers = _pointers.values.toList(growable: false);
246+
final delta = pointers.first - pointers.last;
247+
pitch = delta.dy.abs() < delta.dx.abs();
248+
}
234249

235250
// zoom
236251
var newZoom = camera.zoom;
237252
final lastScale = lastEvent?.scale ?? 1.0;
238253
final scaleDelta = details.scale - lastScale;
239-
if (scaleDelta != 0 && options.gestures.zoom) {
254+
if (scaleDelta != 0 && options.gestures.zoom && !pitch) {
240255
const scaleSensitivity = 1.0;
241256
newZoom = camera.zoom + scaleDelta * scaleSensitivity;
242257
}
243258

244259
// center
245260
var newCenter = camera.center;
246-
if (options.gestures.pan) {
247-
final lastPointerOffset =
248-
lastEvent?.focalPoint ?? startEvent.focalPoint;
261+
if (options.gestures.pan && !pitch) {
249262
final delta = details.focalPoint - lastPointerOffset;
250263
final centerOffset = toScreenLocation(camera.center);
251264
final newCenterOffset = centerOffset - delta;
@@ -254,18 +267,30 @@ abstract class MapLibreMapState extends State<MapLibreMap>
254267

255268
// bearing
256269
var newBearing = camera.bearing;
257-
if (options.gestures.rotate && details.rotation != 0.0) {
270+
if (options.gestures.rotate && details.rotation != 0.0 && !pitch) {
258271
final lastRotation = lastEvent?.rotation ?? 0.0;
259272
final rotationDelta = details.rotation - lastRotation;
260273
newBearing = camera.bearing - rotationDelta * radian2Degree;
261274
}
262275

263-
moveCamera(zoom: newZoom, center: newCenter, bearing: newBearing);
276+
// pitch
277+
var newPitch = camera.pitch;
278+
if (options.gestures.pitch && pitch) {
279+
final delta = details.focalPoint - lastPointerOffset;
280+
newPitch = camera.pitch - delta.dy * 0.5; // sensitivity;
281+
}
282+
283+
moveCamera(
284+
zoom: newZoom,
285+
center: newCenter,
286+
bearing: newBearing,
287+
pitch: newPitch,
288+
);
264289
}
265290
}
266291

267292
void _onScaleEnd(ScaleEndDetails details) {
268-
debugPrint('Scale end: $details');
293+
// debugPrint('Scale end: $details');
269294
final camera = this.camera!;
270295
final firstEvent = _onScaleStartEvent;
271296
final secondToLastEvent = _secondToLastScaleUpdateDetails;
@@ -274,7 +299,6 @@ abstract class MapLibreMapState extends State<MapLibreMap>
274299

275300
// zoom out
276301
if (lastEvent == null && options.gestures.zoom) {
277-
debugPrint('### Zoom out on scale end');
278302
var newCenter = camera.center;
279303
if (options.gestures.pan) {
280304
newCenter = toLngLat(

maplibre/lib/src/platform/web/map_state.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ final class MapLibreMapStateWeb extends MapLibreMapState {
5555
_htmlElement.addEventListener(
5656
'contextmenu',
5757
(Event event) {
58-
print('context menu event prevented');
58+
debugPrint('context menu event prevented');
5959
event.preventDefault();
6060
}.toJS,
6161
);

0 commit comments

Comments
 (0)