@@ -6,6 +6,10 @@ final _nullLatLngBounds = LatLngBounds(
66 southwest: _nullLatLng,
77);
88
9+ // Defaults taken from the Google Maps Platform SDK documentation.
10+ final _defaultStrokeColor = Colors .black.value;
11+ final _defaultFillColor = Colors .transparent.value;
12+
913// Indices in the plugin side don't match with the ones
1014// in the gmaps lib. This translates from plugin -> gmaps.
1115final _mapTypeToMapTypeId = {
@@ -75,7 +79,10 @@ gmaps.MapOptions _rawOptionsToGmapsOptions(Map<String, dynamic> rawOptions) {
7579 return options;
7680}
7781
78- gmaps.MapOptions _setInitialPosition (Map <String , dynamic > rawOptions, gmaps.MapOptions options) {
82+ gmaps.MapOptions _applyInitialPosition (
83+ Map <String , dynamic > rawOptions,
84+ gmaps.MapOptions options,
85+ ) {
7986 // Adjust the initial position, if passed...
8087 Map <String , dynamic > initialPosition = rawOptions['initialCameraPosition' ];
8188 if (initialPosition != null ) {
@@ -198,11 +205,13 @@ List<gmaps.MapTypeStyle> _mapStyles(String mapStyleJson) {
198205 return styles;
199206}
200207
201- gmaps.LatLng _latlngToGmLatlng (LatLng latLng) {
208+ gmaps.LatLng _latLngToGmLatLng (LatLng latLng) {
209+ if (latLng == null ) return null ;
202210 return gmaps.LatLng (latLng.latitude, latLng.longitude);
203211}
204212
205- LatLng _gmLatlngToLatlng (gmaps.LatLng latLng) {
213+ LatLng _gmLatLngToLatLng (gmaps.LatLng latLng) {
214+ if (latLng == null ) return _nullLatLng;
206215 return LatLng (latLng.lat, latLng.lng);
207216}
208217
@@ -212,41 +221,53 @@ LatLngBounds _gmLatLngBoundsTolatLngBounds(gmaps.LatLngBounds latLngBounds) {
212221 }
213222
214223 return LatLngBounds (
215- southwest: _gmLatlngToLatlng (latLngBounds.southWest),
216- northeast: _gmLatlngToLatlng (latLngBounds.northEast),
224+ southwest: _gmLatLngToLatLng (latLngBounds.southWest),
225+ northeast: _gmLatLngToLatLng (latLngBounds.northEast),
217226 );
218227}
219228
220229CameraPosition _gmViewportToCameraPosition (gmaps.GMap map) {
221230 return CameraPosition (
222- target: _gmLatlngToLatlng (map.center),
231+ target: _gmLatLngToLatLng (map.center),
223232 bearing: map.heading ?? 0 ,
224- tilt: map.tilt,
225- zoom: map.zoom.toDouble (),
233+ tilt: map.tilt ?? 0 ,
234+ zoom: map.zoom? .toDouble () ?? 10 ,
226235 );
227236}
228237
229238Set <Marker > _rawOptionsToInitialMarkers (Map <String , dynamic > rawOptions) {
230239 final List <Map <String , dynamic >> list = rawOptions['markersToAdd' ];
231240 Set <Marker > markers = {};
232241 markers.addAll (list? .map ((rawMarker) {
233- Offset offset =
234- Offset ((rawMarker['anchor' ][0 ]), (rawMarker['anchor' ][1 ]));
242+ Offset offset;
243+ LatLng position;
244+ InfoWindow infoWindow;
245+ if (rawMarker['anchor' ] != null ) {
246+ offset = Offset ((rawMarker['anchor' ][0 ]), (rawMarker['anchor' ][1 ]));
247+ }
248+ if (rawMarker['position' ] != null ) {
249+ position = LatLng .fromJson (rawMarker['position' ]);
250+ }
251+ if (rawMarker['infoWindow' ] != null || rawMarker['snippet' ] != null ) {
252+ String title = rawMarker['infoWindow' ] != null
253+ ? rawMarker['infoWindow' ]['title' ]
254+ : null ;
255+ infoWindow = InfoWindow (
256+ title: title ?? '' ,
257+ snippet: rawMarker['snippet' ] ?? '' ,
258+ );
259+ }
235260 return Marker (
236261 markerId: MarkerId (rawMarker['markerId' ]),
237262 alpha: rawMarker['alpha' ],
238263 anchor: offset,
239264 consumeTapEvents: rawMarker['consumeTapEvents' ],
240265 draggable: rawMarker['draggable' ],
241266 flat: rawMarker['flat' ],
242- icon: BitmapDescriptor
243- .defaultMarker, // TODO: Doesn't this support custom icons?
244- infoWindow: InfoWindow (
245- title: rawMarker['infoWindow' ]['title' ] ?? '' ,
246- snippet: rawMarker['snippet' ],
247- anchor: offset, // TODO: Check this value. Is it correct?
248- ),
249- position: LatLng .fromJson (rawMarker['position' ]),
267+ // TODO: Doesn't this support custom icons?
268+ icon: BitmapDescriptor .defaultMarker,
269+ infoWindow: infoWindow,
270+ position: position ?? _nullLatLng,
250271 rotation: rawMarker['rotation' ],
251272 visible: rawMarker['visible' ],
252273 zIndex: rawMarker['zIndex' ],
@@ -260,13 +281,17 @@ Set<Circle> _rawOptionsToInitialCircles(Map<String, dynamic> rawOptions) {
260281 final List <Map <String , dynamic >> list = rawOptions['circlesToAdd' ];
261282 Set <Circle > circles = {};
262283 circles.addAll (list? .map ((rawCircle) {
284+ LatLng center;
285+ if (rawCircle['center' ] != null ) {
286+ center = LatLng .fromJson (rawCircle['center' ]);
287+ }
263288 return Circle (
264289 circleId: CircleId (rawCircle['circleId' ]),
265290 consumeTapEvents: rawCircle['consumeTapEvents' ],
266- fillColor: Color (rawCircle['fillColor' ]),
267- center: LatLng . fromJson (rawCircle[ ' center' ]) ,
291+ fillColor: Color (rawCircle['fillColor' ] ?? _defaultFillColor ),
292+ center: center ?? _nullLatLng ,
268293 radius: rawCircle['radius' ],
269- strokeColor: Color (rawCircle['strokeColor' ]),
294+ strokeColor: Color (rawCircle['strokeColor' ] ?? _defaultStrokeColor ),
270295 strokeWidth: rawCircle['strokeWidth' ],
271296 visible: rawCircle['visible' ],
272297 zIndex: rawCircle['zIndex' ],
@@ -284,7 +309,7 @@ Set<Polyline> _rawOptionsToInitialPolylines(Map<String, dynamic> rawOptions) {
284309 return Polyline (
285310 polylineId: PolylineId (rawPolyline['polylineId' ]),
286311 consumeTapEvents: rawPolyline['consumeTapEvents' ],
287- color: Color (rawPolyline['color' ]),
312+ color: Color (rawPolyline['color' ] ?? _defaultStrokeColor ),
288313 geodesic: rawPolyline['geodesic' ],
289314 visible: rawPolyline['visible' ],
290315 zIndex: rawPolyline['zIndex' ],
@@ -306,9 +331,9 @@ Set<Polygon> _rawOptionsToInitialPolygons(Map<String, dynamic> rawOptions) {
306331 return Polygon (
307332 polygonId: PolygonId (rawPolygon['polygonId' ]),
308333 consumeTapEvents: rawPolygon['consumeTapEvents' ],
309- fillColor: Color (rawPolygon['fillColor' ]),
334+ fillColor: Color (rawPolygon['fillColor' ] ?? _defaultFillColor ),
310335 geodesic: rawPolygon['geodesic' ],
311- strokeColor: Color (rawPolygon['strokeColor' ]),
336+ strokeColor: Color (rawPolygon['strokeColor' ] ?? _defaultStrokeColor ),
312337 strokeWidth: rawPolygon['strokeWidth' ],
313338 visible: rawPolygon['visible' ],
314339 zIndex: rawPolygon['zIndex' ],
@@ -403,7 +428,7 @@ gmaps.PolygonOptions _polygonOptionsFromPolygon(
403428 gmaps.GMap googleMap, Polygon polygon) {
404429 List <gmaps.LatLng > paths = [];
405430 polygon.points.forEach ((point) {
406- paths.add (_latlngToGmLatlng (point));
431+ paths.add (_latLngToGmLatLng (point));
407432 });
408433 return gmaps.PolygonOptions ()
409434 ..paths = paths
@@ -421,7 +446,7 @@ gmaps.PolylineOptions _polylineOptionsFromPolyline(
421446 gmaps.GMap googleMap, Polyline polyline) {
422447 List <gmaps.LatLng > paths = [];
423448 polyline.points.forEach ((point) {
424- paths.add (_latlngToGmLatlng (point));
449+ paths.add (_latLngToGmLatLng (point));
425450 });
426451
427452 return gmaps.PolylineOptions ()
@@ -467,13 +492,22 @@ void _applyCameraUpdate(gmaps.GMap map, CameraUpdate update) {
467492 map.panBy (json[1 ], json[2 ]);
468493 break ;
469494 case 'zoomBy' :
495+ gmaps.LatLng focusLatLng;
470496 double zoomDelta = json[1 ] ?? 0 ;
471497 // Web only supports integer changes...
472498 int newZoomDelta = zoomDelta < 0 ? zoomDelta.floor () : zoomDelta.ceil ();
473- map.zoom = map.zoom + newZoomDelta;
474499 if (json.length == 3 ) {
475500 // With focus
476- map.panTo (gmaps.LatLng (json[2 ][0 ], json[2 ][1 ]));
501+ try {
502+ focusLatLng = _pixelToLatLng (map, json[2 ][0 ], json[2 ][1 ]);
503+ } catch (e) {
504+ // https://github.com/a14n/dart-google-maps/issues/87
505+ // print('Error computing new focus LatLng. JS Error: ' + e.toString());
506+ }
507+ }
508+ map.zoom = map.zoom + newZoomDelta;
509+ if (focusLatLng != null ) {
510+ map.panTo (focusLatLng);
477511 }
478512 break ;
479513 case 'zoomIn' :
@@ -489,3 +523,20 @@ void _applyCameraUpdate(gmaps.GMap map, CameraUpdate update) {
489523 throw UnimplementedError ('Unimplemented CameraMove: ${json [0 ]}.' );
490524 }
491525}
526+
527+ // original JS by: Byron Singh (https://stackoverflow.com/a/30541162)
528+ gmaps.LatLng _pixelToLatLng (gmaps.GMap map, int x, int y) {
529+ final ne = map.bounds.northEast;
530+ final sw = map.bounds.southWest;
531+ final projection = map.projection;
532+
533+ final topRight = projection.fromLatLngToPoint (ne);
534+ final bottomLeft = projection.fromLatLngToPoint (sw);
535+
536+ final scale = 1 << map.zoom; // 2 ^ zoom
537+
538+ final point =
539+ gmaps.Point ((x / scale) + bottomLeft.x, (y / scale) + topRight.y);
540+
541+ return projection.fromPointToLatLng (point);
542+ }
0 commit comments