Skip to content

Commit

Permalink
[google_maps_flutter_platform_interface] Platform interface changes t…
Browse files Browse the repository at this point in the history
…o support heatmaps (#7312)

Prequel to:
- #7313
- #7314
- #7315
- #3257
  • Loading branch information
Rexios80 authored Aug 5, 2024
1 parent c451af7 commit 9308857
Show file tree
Hide file tree
Showing 12 changed files with 1,036 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.9.0

* Adds support for heatmap layers.

## 2.8.0

* Deprecates `BitmapDescriptor.fromAssetImage` in favor of `BitmapDescriptor.asset` and `AssetMapBitmap.create`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:stream_transform/stream_transform.dart';
import '../../google_maps_flutter_platform_interface.dart';
import '../types/tile_overlay_updates.dart';
import '../types/utils/map_configuration_serialization.dart';
import 'serialization.dart';

/// Error thrown when an unknown map ID is provided to a method channel API.
class UnknownMapIDError extends Error {
Expand Down Expand Up @@ -363,6 +364,17 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform {
);
}

@override
Future<void> updateHeatmaps(
HeatmapUpdates heatmapUpdates, {
required int mapId,
}) {
return channel(mapId).invokeMethod<void>(
'heatmaps#update',
serializeMapsObjectUpdates(heatmapUpdates, serializeHeatmap),
);
}

@override
Future<void> updateTileOverlays({
required Set<TileOverlay> newTileOverlays,
Expand Down Expand Up @@ -542,6 +554,7 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform {
'polygonsToAdd': serializePolygonSet(mapObjects.polygons),
'polylinesToAdd': serializePolylineSet(mapObjects.polylines),
'circlesToAdd': serializeCircleSet(mapObjects.circles),
'heatmapsToAdd': serializeHeatmapSet(mapObjects.heatmaps),
'tileOverlaysToAdd': serializeTileOverlaySet(mapObjects.tileOverlays),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import '../../google_maps_flutter_platform_interface.dart';

String _objectsToAddKey(String name) => '${name}sToAdd';
String _objectsToChangeKey(String name) => '${name}sToChange';
String _objectIdsToRemoveKey(String name) => '${name}IdsToRemove';
const String _heatmapIdKey = 'heatmapId';
const String _heatmapDataKey = 'data';
const String _heatmapDissipatingKey = 'dissipating';
const String _heatmapGradientKey = 'gradient';
const String _heatmapMaxIntensityKey = 'maxIntensity';
const String _heatmapOpacityKey = 'opacity';
const String _heatmapRadiusKey = 'radius';
const String _heatmapMinimumZoomIntensityKey = 'minimumZoomIntensity';
const String _heatmapMaximumZoomIntensityKey = 'maximumZoomIntensity';
const String _heatmapGradientColorsKey = 'colors';
const String _heatmapGradientStartPointsKey = 'startPoints';
const String _heatmapGradientColorMapSizeKey = 'colorMapSize';

void _addIfNonNull(Map<String, Object?> map, String fieldName, Object? value) {
if (value != null) {
map[fieldName] = value;
}
}

/// Serialize [MapsObjectUpdates]
Object serializeMapsObjectUpdates<T extends MapsObject<T>>(
MapsObjectUpdates<T> updates,
Object Function(T) serialize,
) {
final Map<String, Object> json = <String, Object>{};

_addIfNonNull(
json,
_objectsToAddKey(updates.objectName),
updates.objectsToAdd.map(serialize).toList(),
);
_addIfNonNull(
json,
_objectsToChangeKey(updates.objectName),
updates.objectsToChange.map(serialize).toList(),
);
_addIfNonNull(
json,
_objectIdsToRemoveKey(updates.objectName),
updates.objectIdsToRemove
.map<String>((MapsObjectId<T> m) => m.value)
.toList(),
);

return json;
}

/// Serialize [Heatmap]
Object serializeHeatmap(Heatmap heatmap) {
final Map<String, Object> json = <String, Object>{};

_addIfNonNull(json, _heatmapIdKey, heatmap.heatmapId.value);
_addIfNonNull(
json,
_heatmapDataKey,
heatmap.data.map(serializeWeightedLatLng).toList(),
);
_addIfNonNull(json, _heatmapDissipatingKey, heatmap.dissipating);

final HeatmapGradient? gradient = heatmap.gradient;
if (gradient != null) {
_addIfNonNull(
json, _heatmapGradientKey, serializeHeatmapGradient(gradient));
}
_addIfNonNull(json, _heatmapMaxIntensityKey, heatmap.maxIntensity);
_addIfNonNull(json, _heatmapOpacityKey, heatmap.opacity);
_addIfNonNull(json, _heatmapRadiusKey, heatmap.radius.radius);
_addIfNonNull(
json, _heatmapMinimumZoomIntensityKey, heatmap.minimumZoomIntensity);
_addIfNonNull(
json, _heatmapMaximumZoomIntensityKey, heatmap.maximumZoomIntensity);

return json;
}

/// Serialize [WeightedLatLng]
Object serializeWeightedLatLng(WeightedLatLng wll) {
return <Object>[serializeLatLng(wll.point), wll.weight];
}

/// Deserialize [WeightedLatLng]
WeightedLatLng? deserializeWeightedLatLng(Object? json) {
if (json == null) {
return null;
}
assert(json is List && json.length == 2);
final List<dynamic> list = json as List<dynamic>;
final LatLng latLng = deserializeLatLng(list[0])!;
return WeightedLatLng(latLng, weight: list[1] as double);
}

/// Serialize [LatLng]
Object serializeLatLng(LatLng latLng) {
return <Object>[latLng.latitude, latLng.longitude];
}

/// Deserialize [LatLng]
LatLng? deserializeLatLng(Object? json) {
if (json == null) {
return null;
}
assert(json is List && json.length == 2);
final List<Object?> list = json as List<Object?>;
return LatLng(list[0]! as double, list[1]! as double);
}

/// Serialize [HeatmapGradient]
Object serializeHeatmapGradient(HeatmapGradient gradient) {
final Map<String, Object> json = <String, Object>{};

_addIfNonNull(
json,
_heatmapGradientColorsKey,
gradient.colors.map((HeatmapGradientColor e) => e.color.value).toList(),
);
_addIfNonNull(
json,
_heatmapGradientStartPointsKey,
gradient.colors.map((HeatmapGradientColor e) => e.startPoint).toList(),
);
_addIfNonNull(json, _heatmapGradientColorMapSizeKey, gradient.colorMapSize);

return json;
}

/// Deserialize [HeatmapGradient]
HeatmapGradient? deserializeHeatmapGradient(Object? json) {
if (json == null) {
return null;
}
assert(json is Map);
final Map<String, Object?> map = (json as Map<Object?, Object?>).cast();
final List<Color> colors = (map[_heatmapGradientColorsKey]! as List<Object?>)
.whereType<int>()
.map((int e) => Color(e))
.toList();
final List<double> startPoints =
(map[_heatmapGradientStartPointsKey]! as List<Object?>)
.whereType<double>()
.toList();
final List<HeatmapGradientColor> gradientColors = <HeatmapGradientColor>[];
for (int i = 0; i < colors.length; i++) {
gradientColors.add(HeatmapGradientColor(colors[i], startPoints[i]));
}
return HeatmapGradient(
gradientColors,
colorMapSize: map[_heatmapGradientColorMapSizeKey] as int? ?? 256,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
throw UnimplementedError('init() has not been implemented.');
}

/// Updates configuration options of the map user interface - deprecated, use
/// updateMapConfiguration instead.
/// Updates configuration options of the map user interface.
///
/// Change listeners are notified once the update has been made on the
/// platform side.
///
/// The returned [Future] completes after listeners have been notified.
@Deprecated('Use updateMapConfiguration instead.')
Future<void> updateMapOptions(
Map<String, dynamic> optionsUpdate, {
required int mapId,
Expand Down Expand Up @@ -129,6 +129,19 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
throw UnimplementedError('updateCircles() has not been implemented.');
}

/// Updates heatmap configuration.
///
/// Change listeners are notified once the update has been made on the
/// platform side.
///
/// The returned [Future] completes after listeners have been notified.
Future<void> updateHeatmaps(
HeatmapUpdates heatmapUpdates, {
required int mapId,
}) {
throw UnimplementedError('updateHeatmaps() has not been implemented.');
}

/// Updates tile overlay configuration.
///
/// Change listeners are notified once the update has been made on the
Expand Down Expand Up @@ -387,8 +400,8 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
return null;
}

/// Returns a widget displaying the map view - deprecated, use
/// [buildViewWithConfiguration] instead.
/// Returns a widget displaying the map view.
@Deprecated('Use buildViewWithConfiguration instead.')
Widget buildView(
int creationId,
PlatformViewCreatedCallback onPlatformViewCreated, {
Expand All @@ -407,8 +420,7 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
throw UnimplementedError('buildView() has not been implemented.');
}

/// Returns a widget displaying the map view - deprecated, use
/// [buildViewWithConfiguration] instead.
/// Returns a widget displaying the map view.
///
/// This method is similar to [buildView], but contains a parameter for
/// platforms that require a text direction.
Expand All @@ -417,6 +429,7 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
/// [buildView]. This is for backward compatibility with existing
/// implementations. Platforms that use the text direction should override
/// this as the primary implementation, and delegate to it from buildView.
@Deprecated('Use buildViewWithConfiguration instead.')
Widget buildViewWithTextDirection(
int creationId,
PlatformViewCreatedCallback onPlatformViewCreated, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ abstract class GoogleMapsInspectorPlatform extends PlatformInterface {
throw UnimplementedError('getTileOverlayInfo() has not been implemented.');
}

/// If the platform supports getting information about heatmaps.
bool supportsGettingHeatmapInfo() {
throw UnimplementedError(
'supportsGettingHeatmapInfo() has not been implemented.',
);
}

/// Returns information about the heatmap with the given ID.
///
/// The returned object will be synthesized from platform data, so will not
/// be the same Dart object as the original [Heatmap] provided to the
/// platform interface with that ID, and not all fields will be populated.
Future<Heatmap?> getHeatmapInfo(HeatmapId heatmapId, {required int mapId}) {
throw UnimplementedError('getHeatmapInfo() has not been implemented.');
}

/// Returns current clusters from [ClusterManager].
Future<List<Cluster>> getClusters(
{required int mapId, required ClusterManagerId clusterManagerId}) {
Expand Down
Loading

0 comments on commit 9308857

Please sign in to comment.