Skip to content

Commit

Permalink
fix: flyTo, jumpTo respect parameters (#12)
Browse files Browse the repository at this point in the history
superseeds #11
  • Loading branch information
josxha authored Sep 14, 2024
1 parent 4ee72bb commit ad9099d
Show file tree
Hide file tree
Showing 17 changed files with 141 additions and 89 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## unreleased

- add `duration` parameter to `flyTo()`
- fix `jumpTo()` never returns

## 0.0.1+1

- fix urls to website
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ welcome.
flutter pub global activate pigeon # only once
dart run pigeon --input pigeons/pigeon.dart
cp ios/Classes/Pigeon.g.swift macos/Classes/Pigeon.g.swift
dart format .
```

#### Test with WebAssembly
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ android {
// implementation 'org.maplibre.gl:android-plugin-offline-v9:3.0.0'
// implementation 'com.squareup.okhttp3:okhttp:4.12.0'
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.mockito:mockito-core:5.0.0")
testImplementation("org.mockito:mockito-core:5.4.0")
}

testOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.maplibre.android.maps.Style
import org.maplibre.android.style.layers.CircleLayer
import org.maplibre.android.style.layers.FillLayer
import org.maplibre.android.style.sources.GeoJsonSource
import kotlin.coroutines.cancellation.CancellationException

class MapLibreMapController(
viewId: Int,
Expand Down Expand Up @@ -72,9 +73,7 @@ class MapLibreMapController(
}
}

override fun getView(): View {
return mapViewContainer;
}
override fun getView(): View = mapViewContainer

override fun onMapReady(mapLibreMap: MapLibreMap) {
this.mapLibreMap = mapLibreMap
Expand All @@ -88,31 +87,49 @@ class MapLibreMapController(
}

override fun dispose() {
// free any resources
}

override fun jumpTo(
center: LngLat,
center: LngLat?,
zoom: Double?,
bearing: Double?,
pitch: Double?,
callback: (Result<Unit>) -> Unit
) {
val latLng = LatLng(center.lat, center.lng);
val cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom ?: 0.0)
val camera = CameraPosition.Builder()
if (center != null) camera.target(LatLng(center.lat, center.lng))
if (zoom != null) camera.zoom(zoom)
if (pitch != null) camera.tilt(pitch)
if (bearing != null) camera.bearing(bearing)
val cameraUpdate = CameraUpdateFactory.newCameraPosition(camera.build())
mapLibreMap.moveCamera(cameraUpdate)
callback(Result.success(Unit));
}

override fun flyTo(
center: LngLat,
center: LngLat?,
zoom: Double?,
bearing: Double?,
pitch: Double?,
durationMs: Long,
callback: (Result<Unit>) -> Unit
) {
val latLng = LatLng(center.lat, center.lng);
val cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom ?: 0.0)
mapLibreMap.animateCamera(cameraUpdate)
callback(Result.success(Unit));
val camera = CameraPosition.Builder()
if (center != null) camera.target(LatLng(center.lat, center.lng))
if (zoom != null) camera.zoom(zoom)
if (pitch != null) camera.tilt(pitch)
if (bearing != null) camera.bearing(bearing)
val cameraUpdate = CameraUpdateFactory.newCameraPosition(camera.build())
mapLibreMap.animateCamera(
cameraUpdate,
durationMs.toInt(),
object : MapLibreMap.CancelableCallback {
override fun onCancel() =
callback(Result.failure(CancellationException("Animation cancelled.")))

override fun onFinish() = callback(Result.success(Unit))
})
}

override fun toScreenLocation(
Expand Down
11 changes: 6 additions & 5 deletions android/src/main/kotlin/com/github/josxha/maplibre/Pigeon.g.kt
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ private open class PigeonPigeonCodec : StandardMessageCodec() {
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface MapLibreHostApi {
/** Move the viewport of the map to a new location without any animation. */
fun jumpTo(center: LngLat, zoom: Double?, bearing: Double?, pitch: Double?, callback: (Result<Unit>) -> Unit)
fun jumpTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, callback: (Result<Unit>) -> Unit)
/** Animate the viewport of the map to a new location. */
fun flyTo(center: LngLat, zoom: Double?, bearing: Double?, pitch: Double?, callback: (Result<Unit>) -> Unit)
fun flyTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, durationMs: Long, callback: (Result<Unit>) -> Unit)
/** Convert a coordinate to a location on the screen. */
fun toScreenLocation(lng: Double, lat: Double, callback: (Result<ScreenLocation>) -> Unit)
/** Convert a screen location to a coordinate. */
Expand All @@ -218,7 +218,7 @@ interface MapLibreHostApi {
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val centerArg = args[0] as LngLat
val centerArg = args[0] as LngLat?
val zoomArg = args[1] as Double?
val bearingArg = args[2] as Double?
val pitchArg = args[3] as Double?
Expand All @@ -240,11 +240,12 @@ interface MapLibreHostApi {
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val centerArg = args[0] as LngLat
val centerArg = args[0] as LngLat?
val zoomArg = args[1] as Double?
val bearingArg = args[2] as Double?
val pitchArg = args[3] as Double?
api.flyTo(centerArg, zoomArg, bearingArg, pitchArg) { result: Result<Unit> ->
val durationMsArg = args[4] as Long
api.flyTo(centerArg, zoomArg, bearingArg, pitchArg, durationMsArg) { result: Result<Unit> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(wrapError(error))
Expand Down
44 changes: 27 additions & 17 deletions example/lib/controller_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// ignore_for_file: prefer_single_quotes, require_trailing_commas

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:maplibre/maplibre.dart';

@immutable
Expand Down Expand Up @@ -29,37 +30,46 @@ class _ControllerPageState extends State<ControllerPage> {
runSpacing: 8,
children: [
OutlinedButton(
onPressed: () {
_controller.jumpTo(
onPressed: () async {
debugPrint('jumpTo start');
await _controller.jumpTo(
center: Position(172.4714, -42.4862),
zoom: 4,
tilt: 0,
bearing: 0,
);
debugPrint('jumpTo end');
},
child: const Text('Move to New Zealand'),
child: const Text('Jump to New Zealand'),
),
OutlinedButton(
onPressed: () {
_controller.flyTo(
center: Position(-18.6874, 64.9445),
zoom: 5,
bearing: -50,
tilt: 60,
);
onPressed: () async {
debugPrint('flyTo start');
try {
await _controller.flyTo(
center: Position(-18.6874, 64.9445),
zoom: 5,
bearing: -50,
tilt: 60,
);
debugPrint('flyTo end');
} catch (error) {
final e = error as PlatformException;
debugPrint(
'flyTo cancelled: code: '
'"${e.code}", message: "${e.message}"',
);
}
},
child: const Text('Animate to Iceland'),
child: const Text('Fly to Iceland'),
),
],
),
),
Expanded(
child: MapLibreMap(
options: MapOptions(
center: Position(9.17, 47.68),
),
options: MapOptions(center: Position(9.17, 47.68), zoom: 3),
onMapCreated: (controller) => _controller = controller,
onStyleLoaded: () async {
debugPrint('[MapLibreMap] onStyleLoadedCallback');
},
),
),
],
Expand Down
11 changes: 6 additions & 5 deletions ios/Classes/Pigeon.g.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,9 @@ class PigeonPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol MapLibreHostApi {
/// Move the viewport of the map to a new location without any animation.
func jumpTo(center: LngLat, zoom: Double?, bearing: Double?, pitch: Double?, completion: @escaping (Result<Void, Error>) -> Void)
func jumpTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, completion: @escaping (Result<Void, Error>) -> Void)
/// Animate the viewport of the map to a new location.
func flyTo(center: LngLat, zoom: Double?, bearing: Double?, pitch: Double?, completion: @escaping (Result<Void, Error>) -> Void)
func flyTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, durationMs: Int64, completion: @escaping (Result<Void, Error>) -> Void)
/// Convert a coordinate to a location on the screen.
func toScreenLocation(lng: Double, lat: Double, completion: @escaping (Result<ScreenLocation, Error>) -> Void)
/// Convert a screen location to a coordinate.
Expand All @@ -256,7 +256,7 @@ class MapLibreHostApiSetup {
if let api = api {
jumpToChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let centerArg = args[0] as! LngLat
let centerArg: LngLat? = nilOrValue(args[0])
let zoomArg: Double? = nilOrValue(args[1])
let bearingArg: Double? = nilOrValue(args[2])
let pitchArg: Double? = nilOrValue(args[3])
Expand All @@ -277,11 +277,12 @@ class MapLibreHostApiSetup {
if let api = api {
flyToChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let centerArg = args[0] as! LngLat
let centerArg: LngLat? = nilOrValue(args[0])
let zoomArg: Double? = nilOrValue(args[1])
let bearingArg: Double? = nilOrValue(args[2])
let pitchArg: Double? = nilOrValue(args[3])
api.flyTo(center: centerArg, zoom: zoomArg, bearing: bearingArg, pitch: pitchArg) { result in
let durationMsArg = args[4] as! Int64
api.flyTo(center: centerArg, zoom: zoomArg, bearing: bearingArg, pitch: pitchArg, durationMs: durationMsArg) { result in
switch result {
case .success:
reply(wrapResult(nil))
Expand Down
13 changes: 8 additions & 5 deletions lib/src/map_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ abstract interface class MapController {

/// Instantly move the map camera to a new location.
Future<void> jumpTo({
required Position center,
Position? center,
double? zoom,
double? bearing,
double? tilt,
});

/// Animate the map camera to a new location.
Future<void> flyTo({
required Position center,
required double zoom,
required double bearing,
required double tilt,
Position? center,
double? zoom,
double? bearing,
double? tilt,
Duration nativeDuration = const Duration(seconds: 2),
double webSpeed = 1.2,
Duration? maxDuration,
});

/// Add a [Marker] to the map.
Expand Down
20 changes: 11 additions & 9 deletions lib/src/native/pigeon.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,10 @@ class MapLibreHostApi {

/// Move the viewport of the map to a new location without any animation.
Future<void> jumpTo({
required LngLat center,
double? zoom,
double? bearing,
double? pitch,
required LngLat? center,
required double? zoom,
required double? bearing,
required double? pitch,
}) async {
final String pigeonVar_channelName =
'dev.flutter.pigeon.maplibre.MapLibreHostApi.jumpTo$pigeonVar_messageChannelSuffix';
Expand All @@ -226,10 +226,11 @@ class MapLibreHostApi {

/// Animate the viewport of the map to a new location.
Future<void> flyTo({
required LngLat center,
double? zoom,
double? bearing,
double? pitch,
required LngLat? center,
required double? zoom,
required double? bearing,
required double? pitch,
required int durationMs,
}) async {
final String pigeonVar_channelName =
'dev.flutter.pigeon.maplibre.MapLibreHostApi.flyTo$pigeonVar_messageChannelSuffix';
Expand All @@ -240,7 +241,8 @@ class MapLibreHostApi {
binaryMessenger: pigeonVar_binaryMessenger,
);
final List<Object?>? pigeonVar_replyList = await pigeonVar_channel
.send(<Object?>[center, zoom, bearing, pitch]) as List<Object?>?;
.send(<Object?>[center, zoom, bearing, pitch, durationMs])
as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
Expand Down
12 changes: 8 additions & 4 deletions lib/src/native/widget_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,34 @@ final class MapLibreMapStateNative extends State<MapLibreMap>

@override
Future<void> jumpTo({
required Position center,
Position? center,
double? zoom,
double? bearing,
double? tilt,
}) =>
_hostApi.jumpTo(
center: center.toLngLat(),
center: center?.toLngLat(),
zoom: zoom,
bearing: bearing,
pitch: tilt,
);

@override
Future<void> flyTo({
required Position center,
Position? center,
double? zoom,
double? bearing,
double? tilt,
Duration nativeDuration = const Duration(seconds: 2),
double webSpeed = 1.2,
Duration? maxDuration,
}) =>
_hostApi.flyTo(
center: center.toLngLat(),
center: center?.toLngLat(),
zoom: zoom,
bearing: bearing,
pitch: tilt,
durationMs: nativeDuration.inMilliseconds,
);

@override
Expand Down
13 changes: 9 additions & 4 deletions lib/src/web/widget_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,14 @@ final class MapLibreMapStateWeb extends State<MapLibreMap>

@override
Future<void> jumpTo({
required Position center,
Position? center,
double? zoom,
double? bearing,
double? tilt,
}) async =>
_map.jumpTo(
interop.JumpToOptions(
center: center.toLngLat(),
center: center?.toLngLat(),
zoom: zoom,
bearing: bearing,
pitch: tilt,
Expand All @@ -199,17 +199,22 @@ final class MapLibreMapStateWeb extends State<MapLibreMap>

@override
Future<void> flyTo({
required Position center,
Position? center,
double? zoom,
double? bearing,
double? tilt,
Duration nativeDuration = const Duration(seconds: 2),
double webSpeed = 1.2,
Duration? maxDuration,
}) async =>
_map.flyTo(
interop.FlyToOptions(
center: center.toLngLat(),
center: center?.toLngLat(),
zoom: zoom,
bearing: bearing,
pitch: tilt,
speed: webSpeed,
maxDuration: maxDuration?.inMilliseconds,
),
);

Expand Down
Loading

0 comments on commit ad9099d

Please sign in to comment.