@@ -6,6 +6,10 @@ final _nullLatLngBounds = LatLngBounds(
6
6
southwest: _nullLatLng,
7
7
);
8
8
9
+ // Defaults taken from the Google Maps Platform SDK documentation.
10
+ final _defaultStrokeColor = Colors .black.value;
11
+ final _defaultFillColor = Colors .transparent.value;
12
+
9
13
// Indices in the plugin side don't match with the ones
10
14
// in the gmaps lib. This translates from plugin -> gmaps.
11
15
final _mapTypeToMapTypeId = {
@@ -75,7 +79,10 @@ gmaps.MapOptions _rawOptionsToGmapsOptions(Map<String, dynamic> rawOptions) {
75
79
return options;
76
80
}
77
81
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
+ ) {
79
86
// Adjust the initial position, if passed...
80
87
Map <String , dynamic > initialPosition = rawOptions['initialCameraPosition' ];
81
88
if (initialPosition != null ) {
@@ -198,11 +205,13 @@ List<gmaps.MapTypeStyle> _mapStyles(String mapStyleJson) {
198
205
return styles;
199
206
}
200
207
201
- gmaps.LatLng _latlngToGmLatlng (LatLng latLng) {
208
+ gmaps.LatLng _latLngToGmLatLng (LatLng latLng) {
209
+ if (latLng == null ) return null ;
202
210
return gmaps.LatLng (latLng.latitude, latLng.longitude);
203
211
}
204
212
205
- LatLng _gmLatlngToLatlng (gmaps.LatLng latLng) {
213
+ LatLng _gmLatLngToLatLng (gmaps.LatLng latLng) {
214
+ if (latLng == null ) return _nullLatLng;
206
215
return LatLng (latLng.lat, latLng.lng);
207
216
}
208
217
@@ -212,41 +221,53 @@ LatLngBounds _gmLatLngBoundsTolatLngBounds(gmaps.LatLngBounds latLngBounds) {
212
221
}
213
222
214
223
return LatLngBounds (
215
- southwest: _gmLatlngToLatlng (latLngBounds.southWest),
216
- northeast: _gmLatlngToLatlng (latLngBounds.northEast),
224
+ southwest: _gmLatLngToLatLng (latLngBounds.southWest),
225
+ northeast: _gmLatLngToLatLng (latLngBounds.northEast),
217
226
);
218
227
}
219
228
220
229
CameraPosition _gmViewportToCameraPosition (gmaps.GMap map) {
221
230
return CameraPosition (
222
- target: _gmLatlngToLatlng (map.center),
231
+ target: _gmLatLngToLatLng (map.center),
223
232
bearing: map.heading ?? 0 ,
224
- tilt: map.tilt,
225
- zoom: map.zoom.toDouble (),
233
+ tilt: map.tilt ?? 0 ,
234
+ zoom: map.zoom? .toDouble () ?? 10 ,
226
235
);
227
236
}
228
237
229
238
Set <Marker > _rawOptionsToInitialMarkers (Map <String , dynamic > rawOptions) {
230
239
final List <Map <String , dynamic >> list = rawOptions['markersToAdd' ];
231
240
Set <Marker > markers = {};
232
241
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
+ }
235
260
return Marker (
236
261
markerId: MarkerId (rawMarker['markerId' ]),
237
262
alpha: rawMarker['alpha' ],
238
263
anchor: offset,
239
264
consumeTapEvents: rawMarker['consumeTapEvents' ],
240
265
draggable: rawMarker['draggable' ],
241
266
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,
250
271
rotation: rawMarker['rotation' ],
251
272
visible: rawMarker['visible' ],
252
273
zIndex: rawMarker['zIndex' ],
@@ -260,13 +281,17 @@ Set<Circle> _rawOptionsToInitialCircles(Map<String, dynamic> rawOptions) {
260
281
final List <Map <String , dynamic >> list = rawOptions['circlesToAdd' ];
261
282
Set <Circle > circles = {};
262
283
circles.addAll (list? .map ((rawCircle) {
284
+ LatLng center;
285
+ if (rawCircle['center' ] != null ) {
286
+ center = LatLng .fromJson (rawCircle['center' ]);
287
+ }
263
288
return Circle (
264
289
circleId: CircleId (rawCircle['circleId' ]),
265
290
consumeTapEvents: rawCircle['consumeTapEvents' ],
266
- fillColor: Color (rawCircle['fillColor' ]),
267
- center: LatLng . fromJson (rawCircle[ ' center' ]) ,
291
+ fillColor: Color (rawCircle['fillColor' ] ?? _defaultFillColor ),
292
+ center: center ?? _nullLatLng ,
268
293
radius: rawCircle['radius' ],
269
- strokeColor: Color (rawCircle['strokeColor' ]),
294
+ strokeColor: Color (rawCircle['strokeColor' ] ?? _defaultStrokeColor ),
270
295
strokeWidth: rawCircle['strokeWidth' ],
271
296
visible: rawCircle['visible' ],
272
297
zIndex: rawCircle['zIndex' ],
@@ -284,7 +309,7 @@ Set<Polyline> _rawOptionsToInitialPolylines(Map<String, dynamic> rawOptions) {
284
309
return Polyline (
285
310
polylineId: PolylineId (rawPolyline['polylineId' ]),
286
311
consumeTapEvents: rawPolyline['consumeTapEvents' ],
287
- color: Color (rawPolyline['color' ]),
312
+ color: Color (rawPolyline['color' ] ?? _defaultStrokeColor ),
288
313
geodesic: rawPolyline['geodesic' ],
289
314
visible: rawPolyline['visible' ],
290
315
zIndex: rawPolyline['zIndex' ],
@@ -306,9 +331,9 @@ Set<Polygon> _rawOptionsToInitialPolygons(Map<String, dynamic> rawOptions) {
306
331
return Polygon (
307
332
polygonId: PolygonId (rawPolygon['polygonId' ]),
308
333
consumeTapEvents: rawPolygon['consumeTapEvents' ],
309
- fillColor: Color (rawPolygon['fillColor' ]),
334
+ fillColor: Color (rawPolygon['fillColor' ] ?? _defaultFillColor ),
310
335
geodesic: rawPolygon['geodesic' ],
311
- strokeColor: Color (rawPolygon['strokeColor' ]),
336
+ strokeColor: Color (rawPolygon['strokeColor' ] ?? _defaultStrokeColor ),
312
337
strokeWidth: rawPolygon['strokeWidth' ],
313
338
visible: rawPolygon['visible' ],
314
339
zIndex: rawPolygon['zIndex' ],
@@ -403,7 +428,7 @@ gmaps.PolygonOptions _polygonOptionsFromPolygon(
403
428
gmaps.GMap googleMap, Polygon polygon) {
404
429
List <gmaps.LatLng > paths = [];
405
430
polygon.points.forEach ((point) {
406
- paths.add (_latlngToGmLatlng (point));
431
+ paths.add (_latLngToGmLatLng (point));
407
432
});
408
433
return gmaps.PolygonOptions ()
409
434
..paths = paths
@@ -421,7 +446,7 @@ gmaps.PolylineOptions _polylineOptionsFromPolyline(
421
446
gmaps.GMap googleMap, Polyline polyline) {
422
447
List <gmaps.LatLng > paths = [];
423
448
polyline.points.forEach ((point) {
424
- paths.add (_latlngToGmLatlng (point));
449
+ paths.add (_latLngToGmLatLng (point));
425
450
});
426
451
427
452
return gmaps.PolylineOptions ()
@@ -467,13 +492,22 @@ void _applyCameraUpdate(gmaps.GMap map, CameraUpdate update) {
467
492
map.panBy (json[1 ], json[2 ]);
468
493
break ;
469
494
case 'zoomBy' :
495
+ gmaps.LatLng focusLatLng;
470
496
double zoomDelta = json[1 ] ?? 0 ;
471
497
// Web only supports integer changes...
472
498
int newZoomDelta = zoomDelta < 0 ? zoomDelta.floor () : zoomDelta.ceil ();
473
- map.zoom = map.zoom + newZoomDelta;
474
499
if (json.length == 3 ) {
475
500
// 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);
477
511
}
478
512
break ;
479
513
case 'zoomIn' :
@@ -489,3 +523,20 @@ void _applyCameraUpdate(gmaps.GMap map, CameraUpdate update) {
489
523
throw UnimplementedError ('Unimplemented CameraMove: ${json [0 ]}.' );
490
524
}
491
525
}
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