Skip to content

Commit 869f211

Browse files
authored
[google_maps_flutter_web] Render custom Marker icons. (flutter#3273)
* Render markers fromBytes. Ensure initial icon is also preserved. Add test. * Opt-out tests from null-safety until plugin is migrated.
1 parent 0506742 commit 869f211

10 files changed

Lines changed: 82 additions & 4 deletions

File tree

packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.1.0+8
2+
3+
* Update `package:google_maps_flutter_platform_interface` to `^1.0.5`.
4+
* Add support for `fromBitmap` BitmapDescriptors. [Issue](https://github.com/flutter/flutter/issues/66622).
5+
16
## 0.1.0+7
27

38
* Substitute `undefined_prefixed_name: ignore` analyzer setting by a `dart:ui` shim with conditional exports. [Issue](https://github.com/flutter/flutter/issues/69309).

packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ Set<Marker> _rawOptionsToInitialMarkers(Map<String, dynamic> rawOptions) {
264264
Offset offset;
265265
LatLng position;
266266
InfoWindow infoWindow;
267+
BitmapDescriptor icon;
267268
if (rawMarker['anchor'] != null) {
268269
offset = Offset((rawMarker['anchor'][0]), (rawMarker['anchor'][1]));
269270
}
@@ -280,15 +281,17 @@ Set<Marker> _rawOptionsToInitialMarkers(Map<String, dynamic> rawOptions) {
280281
);
281282
}
282283
}
284+
if (rawMarker['icon'] != null) {
285+
icon = BitmapDescriptor.fromJson(rawMarker['icon']);
286+
}
283287
return Marker(
284288
markerId: MarkerId(rawMarker['markerId']),
285289
alpha: rawMarker['alpha'],
286290
anchor: offset,
287291
consumeTapEvents: rawMarker['consumeTapEvents'],
288292
draggable: rawMarker['draggable'],
289293
flat: rawMarker['flat'],
290-
// TODO: Doesn't this support custom icons?
291-
icon: BitmapDescriptor.defaultMarker,
294+
icon: icon,
292295
infoWindow: infoWindow,
293296
position: position ?? _nullLatLng,
294297
rotation: rawMarker['rotation'],
@@ -432,6 +435,11 @@ gmaps.MarkerOptions _markerOptionsFromMarker(
432435
..size = size
433436
..scaledSize = size;
434437
}
438+
} else if (iconConfig[0] == 'fromBytes') {
439+
// Grab the bytes, and put them into a blob
440+
List<int> bytes = iconConfig[1];
441+
final blob = Blob([bytes]); // Let the browser figure out the encoding
442+
icon = gmaps.Icon()..url = Url.createObjectUrlFromBlob(blob);
435443
}
436444
}
437445
return gmaps.MarkerOptions()

packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: google_maps_flutter_web
22
description: Web platform implementation of google_maps_flutter
33
homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter
4-
version: 0.1.0+7
4+
version: 0.1.0+8
55

66
flutter:
77
plugin:
@@ -16,14 +16,15 @@ dependencies:
1616
flutter_web_plugins:
1717
sdk: flutter
1818
meta: ^1.1.7
19-
google_maps_flutter_platform_interface: ^1.0.4
19+
google_maps_flutter_platform_interface: ^1.0.5
2020
google_maps: ^3.4.5
2121
stream_transform: ^1.2.0
2222
sanitize_html: ^1.4.1
2323

2424
dev_dependencies:
2525
flutter_test:
2626
sdk: flutter
27+
http: ^0.12.2
2728
url_launcher: ^5.2.5
2829
pedantic: ^1.8.0
2930
mockito: ^4.1.1

packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/google_maps_controller_integration.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// @dart = 2.9
6+
57
import 'dart:async';
68

79
import 'package:integration_test/integration_test.dart';

packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/google_maps_plugin_integration.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// @dart = 2.9
6+
57
import 'dart:async';
68

79
import 'package:integration_test/integration_test.dart';

packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/marker_integration.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// @dart = 2.9
6+
57
import 'dart:async';
68

79
import 'package:integration_test/integration_test.dart';

packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/markers_integration.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// @dart = 2.9
6+
57
import 'dart:async';
8+
import 'dart:convert';
69
import 'dart:html';
710

11+
import 'package:http/http.dart' as http;
812
import 'package:integration_test/integration_test.dart';
913
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
1014
import 'package:google_maps_flutter_web/google_maps_flutter_web.dart';
1115
import 'package:flutter_test/flutter_test.dart';
1216

17+
import 'resources/icon_image_base64.dart';
18+
1319
void main() {
1420
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
1521

@@ -141,6 +147,30 @@ void main() {
141147
expect(controller.markers[MarkerId('1')].marker.icon, isNull);
142148
});
143149

150+
//
151+
testWidgets('markers with custom bitmap icon work',
152+
(WidgetTester tester) async {
153+
final bytes = Base64Decoder().convert(iconImageBase64);
154+
final markers = {
155+
Marker(
156+
markerId: MarkerId('1'), icon: BitmapDescriptor.fromBytes(bytes)),
157+
};
158+
159+
controller.addMarkers(markers);
160+
161+
expect(controller.markers.length, 1);
162+
expect(controller.markers[MarkerId('1')].marker.icon, isNotNull);
163+
expect(controller.markers[MarkerId('1')].marker.icon.url,
164+
startsWith('blob:'));
165+
166+
final blobUrl = controller.markers[MarkerId('1')].marker.icon.url;
167+
final response = await http.get(blobUrl);
168+
169+
expect(response.bodyBytes, bytes,
170+
reason:
171+
'Bytes from the Icon blob must match bytes used to create Marker');
172+
});
173+
144174
// https://github.com/flutter/flutter/issues/67854
145175
testWidgets('InfoWindow snippet can have links',
146176
(WidgetTester tester) async {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
final iconImageBase64 =
2+
'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAIRlWElmTU'
3+
'0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIA'
4+
'AIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQ'
5+
'AAABCgAwAEAAAAAQAAABAAAAAAx28c8QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1M'
6+
'OmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIH'
7+
'g6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8v'
8+
'd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcm'
9+
'lwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFk'
10+
'b2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk'
11+
'9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6'
12+
'eG1wbWV0YT4KTMInWQAAAplJREFUOBF1k01ME1EQx2fe7tIPoGgTE6AJgQQSPaiH9oAtkFbsgX'
13+
'jygFcT0XjSkxcTDxtPJh6MR28ePMHBBA8cNLSIony0oBhEMVETP058tE132+7uG3cW24DAXN57'
14+
'2fn9/zPz3iIcEdEl0nIxtNLr1IlVeoMadkubKmoL+u2SzAV8IjV5Ekt4GN+A8+VOUPwLarOI2G'
15+
'Vpqq0i4JQorwQxPtWHVZ1IKP8LNGDXGaSyqARFxDGo7MJBy4XVf3AyQ+qTHnTEXoF9cFUy3OkY'
16+
'0oWxmWFtD5xNoc1sQ6AOn1+hCNTkkhKow8KFZV77tVs2O9dhFvBm0IA/U0RhZ7/ocEx23oUDlh'
17+
'h8HkNjZIN8Lb3gOU8gOp7AKJHCB2/aNZkTftHumNzzbtl2CBPZHqxw8mHhVZBeoz6w5DvhE2FZ'
18+
'lQYPjKdd2/qRyKZ6KsPv7TEk7EYEk0A0EUmJduHRy1i4oLKqgmC59ZggAdwrC9pFuWy1iUT2rA'
19+
'uv0h2UdNtNqxCBBkgqorjOMOgksN7CxQ90vEb00U3c3LIwyo9o8FXxQVNr8Coqyk+S5EPBXnjt'
20+
'xRmc4TegI7qWbvBkeeUbGMnTCd4nZnYeDOWIEtlC6cKK/JJepY3hZSvN33jovO6L0XFqPKqBTO'
21+
'FuapUoPr1lxDM7cmC2TAOz25cYSGa++feBew/cjpc0V+mNT29/HZp3KDFTNLvuTRPEHy5065lj'
22+
'Xn4y41XM+wP/AlcycRmdc3MUhvLm/J/ceu/3qUVT62oP2EZpjSylHybHSpDUVcjq9gEBVo0+Xt'
23+
'JyN2IWRO+3QUforRoKnZLVsglaMECW+YmMSj9M3SrC6Lg71CMiqWfUrJ6ywzefhnZ+G69BaKdB'
24+
'WhXQAn6wzDUpfUPw7MrmX/WhbfmKblw+AAAAAElFTkSuQmCC';

packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/shape_integration.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// @dart = 2.9
6+
57
import 'dart:async';
68

79
import 'package:integration_test/integration_test.dart';

packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/shapes_integration.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// @dart = 2.9
6+
57
import 'dart:async';
68
import 'dart:ui';
79

0 commit comments

Comments
 (0)