Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
tile overlay
format

doc updates

compelete tests
  • Loading branch information
Chris Yang committed Jan 21, 2021
commit f34a94af02a3382d950164cba09430f61b6daa66
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0

* Add TileOverlay support.

## 1.1.0

* Add support for holes in Polygons.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform {
return _channels[mapId];
}

// Keep a collection of id -> GetTileCallback
// Every method call passes the int mapId
final Map<int, MapGetTileCallback> _getTileCallbacks = {};

/// Initializes the platform interface with [id].
///
/// This method is called when the plugin is first initialized.
Expand Down Expand Up @@ -184,6 +188,15 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform {
LatLng.fromJson(call.arguments['position']),
));
break;
case 'tileOverlay#getTile':
final getTileCallback = _getTileCallbacks[mapId];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: specify type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

final Tile tile = await getTileCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if getTileCallback is null?

call.arguments['tileOverlayId'],
call.arguments['x'],
call.arguments['y'],
call.arguments['zoom'],
);
return tile.toJson();
default:
throw MissingPluginException();
}
Expand Down Expand Up @@ -281,6 +294,40 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform {
);
}

/// Updates tile overlay configuration.
///
/// Change listeners are notified once the update has been made on the
/// platform side.
///
/// The returned [Future] completes after listeners have been notified.
@override
Future<void> updateTileOverlays(
TileOverlayUpdates tileOverlayUpdates, {
@required int mapId,
}) {
assert(tileOverlayUpdates != null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to update _tileOverlays here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, also removed setTileOverlays

return channel(mapId).invokeMethod<void>(
'tileOverlays#update',
tileOverlayUpdates.toJson(),
);
}

/// Clears the tile cache so that all tiles will be requested again from the
/// [TileProvider]. The current tiles from this tile overlay will also be
/// cleared from the map after calling this method. The API maintains a small
/// in-memory cache of tiles. If you want to cache tiles for longer, you
/// should implement an on-disk cache.
@override
Future<void> clearTileCache(
TileOverlayId tileOverlayId, {
@required int mapId,
}) {
return channel(mapId)
.invokeMethod<void>('tileOverlays#clearTileCache', <String, dynamic>{
'tileOverlayId': tileOverlayId.value,
});
}

/// Starts an animated change of the map camera position.
///
/// The returned [Future] completes after the change has been started on the
Expand Down Expand Up @@ -451,6 +498,16 @@ class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform {
return channel(mapId).invokeMethod<Uint8List>('map#takeSnapshot');
}

/// Sets the `MapGetTileCallback` with mapId.
///
/// `mapId` and `callback` must not be null.
@override
void setGetTileCallback(
{@required int mapId, @required MapGetTileCallback callback}) {
assert(mapId != null && callback != null);
_getTileCallbacks[mapId] = callback;
}

/// This method builds the appropriate platform view where the map
/// can be rendered.
/// The `mapId` is passed as a parameter from the framework on the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import 'package:google_maps_flutter_platform_interface/src/method_channel/method
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

/// Callback method for when a [Tile] is requested from a [TileProvider].
typedef Future<Tile> MapGetTileCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

TileOverlayId tileOverlayId, int x, int y, int zoom);

/// The interface that platform-specific implementations of `google_maps_flutter` must extend.
///
/// Avoid `implements` of this interface. Using `implements` makes adding any new
Expand Down Expand Up @@ -115,6 +119,31 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
throw UnimplementedError('updateCircles() has not been implemented.');
}

/// Updates tile overlay 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> updateTileOverlays(
TileOverlayUpdates tileOverlayUpdates, {
@required int mapId,
}) {
throw UnimplementedError('updateTileOverlays() has not been implemented.');
}

/// Clears the tile cache so that all tiles will be requested again from the
/// [TileProvider]. The current tiles from this tile overlay will also be
/// cleared from the map after calling this method. The API maintains a small
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the API you mean the Google Maps SDK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I replaced it with Google Maps SDK

/// in-memory cache of tiles. If you want to cache tiles for longer, you
/// should implement an on-disk cache.
Future<void> clearTileCache(
TileOverlayId tileOverlayId, {
@required int mapId,
}) {
throw UnimplementedError('clearTileCache() has not been implemented.');
}

/// Starts an animated change of the map camera position.
///
/// The returned [Future] completes after the change has been started on the
Expand Down Expand Up @@ -246,6 +275,12 @@ abstract class GoogleMapsFlutterPlatform extends PlatformInterface {
throw UnimplementedError('takeSnapshot() has not been implemented.');
}

/// Set the [MapGetTileCallback] for the map, which will be called
/// when a [Tile] is requested for an added [TileProvider].
void setGetTileCallback({@required int mapId, MapGetTileCallback callback}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand why we need this method?
When we pass the platform overlays to the platform side in updateTileOverlays we already pass each overlay with it's associated TileProvider, is it possible for the platform side to use that information to cache the provider for each overlay?

Adding this extra method for setting a global provider for all overlays adds an opportunity for multiple (and potentially inconsistent) source of truth regarding the tile for a given overlay at a given coordinate.

Or am I completely missing something?

throw UnimplementedError('onGetTile() has not been implemented.');
}

// The following are the 11 possible streams of data from the native side
// into the plugin

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2018 The Chromium 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 'dart:typed_data';
import 'package:meta/meta.dart' show immutable;

/// Contains information about a Tile that is returned by a [TileProvider].
@immutable
class Tile {
/// Creates an immutable representation of a [Tile] to draw by [TileProvider].
const Tile(this.width, this.height, this.data);

/// The width of the image encoded by data in pixels.
final int width;

/// The height of the image encoded by data in pixels.
final int height;

/// A byte array containing the image data.
final Uint8List data;

/// Converts this object to JSON.
dynamic toJson() {
final Map<String, dynamic> json = <String, dynamic>{};

void addIfPresent(String fieldName, dynamic value) {
if (value != null) {
json[fieldName] = value;
}
}

addIfPresent('width', width);
addIfPresent('height', height);
addIfPresent('data', data);

return json;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Copyright 2018 The Chromium 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 'types.dart';
import 'package:meta/meta.dart' show immutable, required;

/// Uniquely identifies a [TileOverlay] among [GoogleMap] tile overlays.
///
/// This does not have to be globally unique, only unique among the list.
@immutable
class TileOverlayId {
/// Creates an immutable identifier for a [TileOverlay].
TileOverlayId(this.value) : assert(value != null);

/// value of the [TileOverlayId].
final String value;

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
final TileOverlayId typedOther = other;
return value == typedOther.value;
}

@override
int get hashCode => value.hashCode;

@override
String toString() {
return 'TileOverlay{value: $value}';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
}

/// A Tile Overlay is a set of images which are displayed on top of the base map tiles.
/// These tiles may be transparent, allowing you to add features to existing maps.
///
/// Tile Coordinates
///
/// Note that the world is projected using the Mercator projection
/// (see [Wikipedia](https://en.wikipedia.org/wiki/Mercator_projection)) with the left (west) side
/// of the map corresponding to -180 degrees of longitude and the right (east) side of the map
/// corresponding to 180 degrees of longitude. To make the map square, the top (north) side of the
/// map corresponds to 85.0511 degrees of latitude and the bottom (south) side of the map
/// corresponds to -85.0511 degrees of latitude. Areas outside this latitude range are not rendered.
///
/// At each zoom level, the map is divided into tiles and only the tiles that overlap the screen are
/// downloaded and rendered. Each tile is square and the map is divided into tiles as follows:
///
/// * At zoom level 0, one tile represents the entire world. The coordinates of that tile are
/// (x, y) = (0, 0).
/// * At zoom level 1, the world is divided into 4 tiles arranged in a 2 x 2 grid.
/// * ...
/// * At zoom level N, the world is divided into 4N tiles arranged in a 2N x 2N grid.
///
/// Note that the minimum zoom level that the camera supports (which can depend on various factors)
/// is GoogleMap.getMinZoomLevel and the maximum zoom level is GoogleMap.getMaxZoomLevel.
///
/// The coordinates of the tiles are measured from the top left (northwest) corner of the map.
/// At zoom level N, the x values of the tile coordinates range from 0 to 2N - 1 and increase from
/// west to east and the y values range from 0 to 2N - 1 and increase from north to south.
///
class TileOverlay {
/// Creates an immutable representation of a [TileOverlay] to draw on [GoogleMap].
const TileOverlay({
@required this.tileOverlayId,
this.fadeIn = true,
this.tileProvider,
this.transparency = 0.0,
this.zIndex,
this.visible = true,
this.tileSize = 256,
}) : assert(transparency >= 0.0 && transparency <= 1.0);

/// Uniquely identifies a [TileOverlay].
final TileOverlayId tileOverlayId;

/// Whether the tiles should fade in. The default is true.
final bool fadeIn;

/// The tile provider to use for this tile overlay.
final TileProvider tileProvider;

/// The transparency of the tile overlay. The default transparency is 0 (opaque).
final double transparency;

/// The tile overlay's zIndex, i.e., the order in which it will be drawn where
/// overlays with larger values are drawn above those with lower values
final int zIndex;

/// The visibility for the tile overlay. The default visibility is true.
final bool visible;

/// Specifies the number of pixels (not points) that the returned tile images will prefer
/// to display as. iOS only.
///
/// Defaults to 256, which is the traditional size of Google Maps tiles.
/// As an example, an application developer may wish to provide retina tiles (512 pixel edge length)
/// on retina devices, to keep the same number of tiles per view as the default value of 256
/// would give on a non-retina device.
final int tileSize;

/// Creates a new [Polygon] object whose values are the same as this instance,
/// unless overwritten by the specified parameters.
TileOverlay copyWith({
TileOverlayId tileOverlayId,
bool fadeInParam,
double transparencyParam,
int zIndexParam,
bool visibleParam,
int tileSizeParam,
}) {
return TileOverlay(
tileOverlayId: tileOverlayId,
fadeIn: fadeInParam ?? fadeIn,
transparency: transparencyParam ?? transparency,
zIndex: zIndexParam ?? zIndex,
visible: visibleParam ?? visible,
tileSize: tileSizeParam ?? tileSize,
);
}

/// Converts this object to JSON.
dynamic toJson() {
final Map<String, dynamic> json = <String, dynamic>{};

void addIfPresent(String fieldName, dynamic value) {
if (value != null) {
json[fieldName] = value;
}
}

addIfPresent('tileOverlayId', tileOverlayId.value);
addIfPresent('fadeIn', fadeIn);
addIfPresent('transparency', transparency);
addIfPresent('zIndex', zIndex);
addIfPresent('visible', visible);
addIfPresent('tileSize', tileSize);

return json;
}

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
final TileOverlay typedOther = other;
return tileOverlayId == typedOther.tileOverlayId &&
fadeIn == typedOther.fadeIn &&
transparency == typedOther.transparency &&
zIndex == typedOther.zIndex &&
visible == typedOther.visible &&
tileSize == typedOther.tileSize;
}

@override
int get hashCode => tileOverlayId.hashCode;
}
Loading