Skip to content

Commit

Permalink
feat: add event system (#34)
Browse files Browse the repository at this point in the history
## Implementation
- [x] android integration
- [x] web integration
- [x] public API
- [x] example app
- [x] changelog
- [x] update docs

## Events
- [x] map created
- [x] style loaded
- [x] clicked
- [x] long clicked
- [x] secondary clicked
- [x] double clicked
- [x] camera changed

More events can be added later.

## Resources
-
https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapEventType/
-
https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-map-view/index.html
  • Loading branch information
josxha authored Sep 20, 2024
1 parent 22f0c5f commit 87b3873
Show file tree
Hide file tree
Showing 51 changed files with 995 additions and 110 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

### Features

- Add sources and layers to the map programmatically.
- Remove sources and layers from the map programmatically.
- Add event system to the map.
- Add and remove sources to the active map style programmatically.
- Add and remove layers to the active map style programmatically.
- Add `duration` parameter to `flyTo()`.
- `flyTo()` returns after the animation completes or throws an exception if it
has been cancelled.

### Bug fixes

- Fix `jumpTo()` never returns
- Fix `jumpTo()` never returns on Android.

## 0.0.1+1

Expand Down
76 changes: 60 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,66 @@ This package provides unofficial Flutter bindings for MapLibre SDKs.
named maplibre-gl) is used for android and in the future for iOS,
windows, macOS and Linux

MapLibre is a permissive and open source solution for the MVT
(Mapbox Vector Tile) standard. By binding to native SDKs the package
accomplishes performant rendering while supporting a lot of complex
MapLibre is a permissive and open source solution for the MVT
(Mapbox Vector Tile) standard. By binding to native SDKs the package
accomplishes performant rendering while supporting a lot of complex
functionality.

<table>
<thead>
<th>Use custom styles for your map</th>
<th>Tilt or rotate your map</th>
</thead>
<tbody>
<tr>
<td><img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/d8e2c7daf15221f716a2ebbd63e57a317cb089ab/docs/static/img/showcase-map.jpg" alt="Custom styled map" /></td>
<td><img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/d8e2c7daf15221f716a2ebbd63e57a317cb089ab/docs/static/img/showcase-tilt.jpg" alt="Tilted and rotated map" /></td>
</tr>
</tbody>
<tbody>
<tr>
<td style="text-align: center;">
<strong>Use custom vector styles</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/d8e2c7daf15221f716a2ebbd63e57a317cb089ab/docs/static/img/showcase-map.jpg" alt="Custom styled map" />
</td>
<td style="text-align: center;">
<strong>Tilt or rotate the map</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/d8e2c7daf15221f716a2ebbd63e57a317cb089ab/docs/static/img/showcase-tilt.jpg" alt="Tilted and rotated map" />
</td>
<td style="text-align: center;">
<strong>Use raster tiles</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/raster_layer.jpg" alt="Fill Layer" />
</td>
</tr>
<tr>
<td style="text-align: center;">
<strong>Add circles</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/circle_layer.jpg" alt="Circle Layer" />
</td>
<td style="text-align: center;">
<strong>Add 3D building outlines</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/fill_extrusion_layer.jpg" alt="Fill Extrusion Layer" />
</td>
<td style="text-align: center;">
<strong>Add polygons</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/fill_layer.jpg" alt="Fill Layer" />
</td>
</tr>
<tr>
<td style="text-align: center;">
<strong>Add heatmaps</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/heatmap_layer.jpg" alt="Fill Layer" />
</td>
<td style="text-align: center;">
<strong>Render elevation</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/hillshade_layer.jpg" alt="Fill Extrusion Layer" />
</td>
<td style="text-align: center;">
<strong>Add lines</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/line_layer.jpg" alt="Fill Layer" />
</td>
</tr>
<tr>
<td style="text-align: center;">
<strong>Add markers</strong>
<img src="https://raw.githubusercontent.com/josxha/flutter-maplibre/427311f8f4577c215bf73caf46e3769629e74e3b/docs/static/img/layers/symbol_layer.jpg" alt="Symbol Layer" />
</td>
<td style="text-align: center;">
</td>
<td style="text-align: center;">
</td>
</tr>
</tbody>
</table>

## Resources
Expand All @@ -56,7 +100,7 @@ the [API docs](https://pub.dev/documentation/maplibre/latest/maplibre/maplibre-l

This package is still a young package and in an early stage.
While it offers a modern implementation, it currently lacks some
functionality. [See our documentation to learn more.](https://flutter-maplibre.pages.dev/docs/features/supported-features)
functionality. [See our documentation to learn more.](https://flutter-maplibre.pages.dev/docs/supported-features)

## Development & Contributing

Expand All @@ -65,10 +109,10 @@ welcome.

#### Run Code Generation

We use code generation from [pigeon](https://pub.dev/packages/pigeon).
We use code generation from [pigeon](https://pub.dev/packages/pigeon).
If you change the file [pigeons/pigeon.dart](pigeons/pigeon.dart) you'll have
to run the code generator.
Use the generator script in the [./pigeons](./pigeons) directory (or run the
Use the generator script in the [./pigeons](./pigeons) directory (or run the
commands manually) to generate the necessary code.

#### Test with WebAssembly
Expand Down
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ linter:
rules:
lines_longer_than_80_chars: false
flutter_style_todos: false
cascade_invocations: false
cascade_invocations: false
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ buildscript {
}

dependencies {
classpath("com.android.tools.build:gradle:8.6.1")
classpath("com.android.tools.build:gradle:7.3.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ class MapLibreMapController(
private val context: Context,
private val lifecycleProvider: LifecycleProvider,
binaryMessenger: BinaryMessenger
) : PlatformView, DefaultLifecycleObserver, OnMapReadyCallback, MapLibreHostApi,
MapLibreMap.OnMapClickListener, MapLibreMap.OnMapLongClickListener {
) : PlatformView, DefaultLifecycleObserver, OnMapReadyCallback, MapLibreHostApi {
private val mapViewContainer = FrameLayout(context)
private lateinit var mapLibreMap: MapLibreMap
private lateinit var mapView: MapView
Expand Down Expand Up @@ -105,10 +104,23 @@ class MapLibreMapController(
override fun onMapReady(mapLibreMap: MapLibreMap) {
this.mapLibreMap = mapLibreMap
if (initialOptions.listensOnClick) {
this.mapLibreMap.addOnMapClickListener(this)
this.mapLibreMap.addOnMapClickListener { latLng ->
flutterApi.onClick(LngLat(latLng.longitude, latLng.latitude)) { }
true
}
}
if (initialOptions.listensOnLongClick) {
this.mapLibreMap.addOnMapLongClickListener(this)
this.mapLibreMap.addOnMapLongClickListener { latLng ->
flutterApi.onLongClick(LngLat(latLng.longitude, latLng.latitude)) { }
true
}
}
this.mapLibreMap.addOnCameraMoveListener {
val position = mapLibreMap.cameraPosition
val target = mapLibreMap.cameraPosition.target!!
val center = LngLat(target.longitude, target.latitude)
val camera = MapCamera(center, position.zoom, position.tilt, position.bearing)
flutterApi.onCameraMoved(camera) {}
}
val style = Style.Builder().fromUri(initialOptions.style)
mapLibreMap.setStyle(style) { loadedStyle ->
Expand Down Expand Up @@ -512,14 +524,4 @@ class MapLibreMapController(

override fun getMetersPerPixelAtLatitude(latitude: Double): Double =
mapLibreMap.projection.getMetersPerPixelAtLatitude(latitude)

override fun onMapClick(point: LatLng): Boolean {
flutterApi.onClick(LngLat(point.longitude, point.latitude)) { }
return true
}

override fun onMapLongClick(point: LatLng): Boolean {
flutterApi.onLongClick(LngLat(point.longitude, point.latitude)) { }
return true
}
}
18 changes: 18 additions & 0 deletions android/src/main/kotlin/com/github/josxha/maplibre/Pigeon.g.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1088,4 +1088,22 @@ class MapLibreFlutterApi(private val binaryMessenger: BinaryMessenger, private v
}
}
}
/** Callback when the map camera changes. */
fun onCameraMoved(cameraArg: MapCamera, callback: (Result<Unit>) -> Unit)
{
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
val channelName = "dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onCameraMoved$separatedMessageChannelSuffix"
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
channel.send(listOf(cameraArg)) {
if (it is List<*>) {
if (it.size > 1) {
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
} else {
callback(Result.success(Unit))
}
} else {
callback(Result.failure(createConnectionError(channelName)))
}
}
}
}
8 changes: 0 additions & 8 deletions docs/docs/features/_category_.json

This file was deleted.

5 changes: 4 additions & 1 deletion docs/docs/getting-started/add-dependency.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ sidebar_position: 1

# Add Dependency

## Use the package from pub.dev

Add `maplibre` to your project by running this command:

```bash
Expand Down Expand Up @@ -42,9 +44,10 @@ list.

```yaml title="pubspec.yaml"
dependencies:
# highlight-next-line
# highlight-start
maplibre:
git:
url: https://github.com/josxha/flutter-maplibre
ref: main # or a specific commit hash
# highlight-end
```
2 changes: 1 addition & 1 deletion docs/docs/getting-started/use-widget.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class MapScreenState extends State<MapScreen> {

The result should look something like this:

![First map](../img/first_map.jpg)
![First map](/img/first_map.jpg)

If the map style isn't specified, the default MapLibre style is used. Use the
style of a tile provider or create and use your own map style.
6 changes: 4 additions & 2 deletions docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ This is the documentation for the unofficial MapLibre Flutter package.

flutter-maplibre provides bindings to MapLibre Native and MapLibre-GL-JS.

- [Getting started](getting-started/add-dependency)
- [Map Styles](map-styles)
- [Getting started](./getting-started/add-dependency)
- [Map Styles](./map-styles)
- [Map Layers](./category/layers)
- [Map Events](./map-events)
8 changes: 8 additions & 0 deletions docs/docs/layers/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Layers",
"position": 5,
"link": {
"type": "generated-index",
"description": "Add or remove layers from the active map style."
}
}
60 changes: 60 additions & 0 deletions docs/docs/layers/circle-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
sidebar_position: 1
description: 'Add Circles to the map.'
---

# Circle Layer

The `CircleLayer` is either used by the map style or can be added to the map
programmatically to symbolize data on the map.

[![Circle Layer](/img/layers/circle_layer.jpg)](/demo/#/layers/circle)

## Basic Usage

```dart
late final MapController _controller;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Events')),
body: MapLibreMap(
options: MapOptions(center: Position(9.17, 47.68)),
onMapCreated: (controller) => _controller = controller,
onStyleLoaded: () async {
// highlight-start
// add the source
const earthquakes = GeoJsonSource(
id: _sourceId,
data:
'https://maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson',
);
await _controller.addSource(earthquakes);
// add the source with a layer on the map
const circleLayer = CircleLayer(id: _layerId, sourceId: _sourceId);
await _controller.addLayer(circleLayer);
// highlight-end
}
),
);
}
```

Check out
the [example app](https://github.com/josxha/flutter-maplibre/blob/main/example/lib/layers_circle_page.dart)
for to learn more.

## Style

Use the `paint` property to style your `CircleLayer` to change the style of the
map.

See
the [MapLibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#circle)
for all available properties.

## Layout

Use the `layout` property to change how the circles behave on the map.
31 changes: 31 additions & 0 deletions docs/docs/layers/fill-extrusion-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
sidebar_position: 1
description: 'Add 3D building outlines to the map.'
---

# Fill Extrusion Layer

The `FillExtrusionLayer` is either used by the map style or can be added to the
map programmatically to symbolize data on the map.

[![Fill Extrusion Layer](/img/layers/fill_extrusion_layer.jpg)](/demo/#/layers/fill-extrusion)

## Basic Usage

Check out
the [example app](https://github.com/josxha/flutter-maplibre/blob/main/example/lib/layers_fill_extrusion_page.dart)
to learn more.

## Style

Use the `paint` property to style your `FillExtrusionLayer` to change the style
of the map.

See
the [MapLibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#fill-extrusion)
for all available properties.

## Layout

Use the `layout` property to change how the
fill extrusions behave on the map.
31 changes: 31 additions & 0 deletions docs/docs/layers/fill-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
sidebar_position: 1
description: 'Add Polygons to the map.'
---

# Fill Layer

The `FillLayer` is either used by the map style or can be added to the map
programmatically to symbolize data on the map.

[![Fill Layer](/img/layers/fill_layer.jpg)](/demo/#/layers/fill)

## Basic Usage

Check out
the [example app](https://github.com/josxha/flutter-maplibre/blob/main/example/lib/layers_fill_page.dart)
to learn more.

## Style

Use the `paint` property to style your `FillLayer` to change the style of the
map.

See
the [MapLibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#fill)
for all available properties.

## Layout

Use the `layout` property to change how the fills
behave on the map.
Loading

0 comments on commit 87b3873

Please sign in to comment.