1
1
import 'dart:async' ;
2
2
import 'dart:math' ;
3
+ import 'dart:ui' ;
3
4
4
5
import 'package:flutter/services.dart' ;
5
6
import 'package:flutter/widgets.dart' ;
@@ -15,18 +16,28 @@ class MapboxOverlay extends StatefulWidget {
15
16
State <StatefulWidget > createState () => new _MapboxOverlayState ();
16
17
}
17
18
19
+
20
+ /// Manages the creation and state of the map.
21
+ /// This includes:
22
+ /// - maintaining the id of the used surface texture
23
+ /// - maintaining the map transformation
24
+ /// - handling gesture input
18
25
class _MapboxOverlayState extends State <MapboxOverlay > {
19
26
bool _initialized = false ;
20
27
int _textureId = - 1 ;
21
28
Offset _scaleStartFocal;
22
29
double _zoom;
23
- Size _size;
30
+ Size _size; // local coordinate system.
24
31
25
- Future <Null > _createMapView (Size size, MapboxMapOptions options) async {
32
+ Future <Null > _createMapView (
33
+ Window window, Size size, MapboxMapOptions options) async {
26
34
_size = size;
35
+
27
36
try {
28
- int textureId = await widget.controller
29
- .create (width: size.width, height: size.height, options: options);
37
+ int textureId = await widget.controller.create (
38
+ width: _size.width * window.devicePixelRatio,
39
+ height: _size.height * window.devicePixelRatio,
40
+ options: options);
30
41
31
42
if (! mounted) {
32
43
return ;
@@ -48,8 +59,7 @@ class _MapboxOverlayState extends State<MapboxOverlay> {
48
59
}
49
60
50
61
if (! _initialized) {
51
- _createMapView (constraints.biggest, widget.options);
52
-
62
+ _createMapView (window, constraints.biggest, widget.options);
53
63
_initialized = true ;
54
64
return new Container ();
55
65
} else {
@@ -67,25 +77,32 @@ class _MapboxOverlayState extends State<MapboxOverlay> {
67
77
});
68
78
}
69
79
80
+ /// Called when the user double taps the screen, results in zooming the map
70
81
void _onDoubleTap () {
82
+ // TODO we currently zoom on center, this needs to be the tapped offset instead
71
83
widget.controller.getZoom ().then ((zoom) {
72
84
zoom++ ;
73
- widget.controller.zoom (zoom, _size.width / 2 , _size.height / 2 , 350 );
85
+ widget.controller.zoom (zoom, _size.width / 2 * window.devicePixelRatio,
86
+ _size.height / 2 * window.devicePixelRatio, 350 );
74
87
});
75
88
}
76
89
90
+ /// Called when the user initiates a scale/pan gesture.
77
91
void _onScaleStart (ScaleStartDetails details) {
78
- _scaleStartFocal = details.focalPoint;
92
+ _scaleStartFocal = localToMapOffset ( details.focalPoint) ;
79
93
_zoom = 0.0 ;
80
94
}
81
95
96
+ /// Called when the user scales or pans the map.
82
97
void _onScaleUpdate (ScaleUpdateDetails details) {
83
- final Offset delta = details.focalPoint - _scaleStartFocal;
98
+ Offset focalGesture = localToMapOffset (details.focalPoint);
99
+ final Offset delta = focalGesture - _scaleStartFocal;
84
100
widget.controller.moveBy (delta.dx, delta.dy, 0 );
85
101
86
102
if (details.scale != 1.0 ) {
87
103
RenderBox renderBox = context.findRenderObject ();
88
- Offset focalPoint = renderBox.globalToLocal (details.focalPoint);
104
+ Offset focalPoint =
105
+ localToMapOffset (renderBox.globalToLocal (details.focalPoint));
89
106
90
107
double newZoom = _zoomLevel (details.scale);
91
108
double _zoomBy = newZoom - _zoom;
@@ -94,15 +111,27 @@ class _MapboxOverlayState extends State<MapboxOverlay> {
94
111
_zoom = newZoom;
95
112
}
96
113
97
- _scaleStartFocal = details.focalPoint;
114
+ _scaleStartFocal = localToMapOffset ( details.focalPoint) ;
98
115
}
99
116
117
+ /// Called when the users stops scaling the map.
100
118
void _onScaleEnd (ScaleEndDetails details) {
101
119
_scaleStartFocal = null ;
102
120
_zoom = null ;
103
121
}
104
122
123
+ /// Calculates a zoom value from a scale gesture detector input.
105
124
double _zoomLevel (double scale) {
106
125
return log (scale) / log (pi / 2 );
107
126
}
127
+
128
+ /// Flutter supports 2 coordinate systems (local and global).
129
+ /// You can convert between the two using box.localToGlobal/globalToLocal.
130
+ /// This does not match what we expect on gl-native so we need to convert
131
+ /// to the offset to match the input on the Android SDK
132
+ Offset localToMapOffset (Offset offset) {
133
+ // TODO replace with MatrixUtils.transformPoint
134
+ return new Offset (offset.dx * window.devicePixelRatio,
135
+ offset.dy * window.devicePixelRatio);
136
+ }
108
137
}
0 commit comments