diff --git a/example/canvas_source/index.dart b/example/canvas_source/index.dart
new file mode 100644
index 0000000..093b884
--- /dev/null
+++ b/example/canvas_source/index.dart
@@ -0,0 +1,44 @@
+import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
+
+void main() {
+ bool isPlaying = true;
+ Mapbox.accessToken =
+ 'pk.eyJ1IjoiYW5kcmVhNjg5IiwiYSI6ImNrNGlsYjhyZDBuYXoza213aWphOGNjZmoifQ.maw_5NsXejG1DoOeOi6hlQ';
+
+ var map = MapboxMap(
+ MapOptions(
+ container: 'map',
+ style: 'mapbox://styles/mapbox/light-v10',
+ zoom: 5,
+ minZoom: 4,
+ center: LngLat(95.8991, 18.0887),
+ ),
+ );
+
+ map.on('load', (_) {
+ map.addSource(
+ 'canvas-source',
+ CanvasSource(
+ canvas: "canvasID",
+ coordinates: [
+ [91.4461, 21.5006],
+ [100.3541, 21.5006],
+ [100.3541, 13.9706],
+ [91.4461, 13.9706]
+ ],
+ animate: true,
+ ));
+
+ map.addLayer(
+ {'id': 'canvas-layer', 'type': 'raster', 'source': 'canvas-source'});
+ });
+ map.on('click', (_) {
+ final source = map.getSource('canvas-source') as CanvasSource?;
+ if (isPlaying) {
+ source?.pause();
+ } else {
+ source?.play();
+ }
+ isPlaying = !isPlaying;
+ });
+}
diff --git a/example/canvas_source/index.html b/example/canvas_source/index.html
new file mode 100644
index 0000000..0040a70
--- /dev/null
+++ b/example/canvas_source/index.html
@@ -0,0 +1,114 @@
+
+
+
+ Display a canvas source
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/examples.json b/example/examples.json
index a55d70f..35e6fc2 100644
--- a/example/examples.json
+++ b/example/examples.json
@@ -18,5 +18,13 @@
{
"title": "Display a popup on hover",
"folder": "popup_on_hover"
+ },
+ {
+ "title": "Display a canvas source",
+ "folder": "canvas_source"
+ },
+ {
+ "title": "Display a video source",
+ "folder": "video_source"
}
]
\ No newline at end of file
diff --git a/example/video_source/index.dart b/example/video_source/index.dart
new file mode 100644
index 0000000..f78b22b
--- /dev/null
+++ b/example/video_source/index.dart
@@ -0,0 +1,45 @@
+import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
+
+void main() {
+ bool isPlaying = true;
+ Mapbox.accessToken =
+ 'pk.eyJ1IjoiYW5kcmVhNjg5IiwiYSI6ImNrNGlsYjhyZDBuYXoza213aWphOGNjZmoifQ.maw_5NsXejG1DoOeOi6hlQ';
+
+ var map = MapboxMap(
+ MapOptions(
+ container: 'map',
+ style: 'mapbox://styles/mapbox/light-v10',
+ zoom: 16,
+ minZoom: 14,
+ center: LngLat(-122.514426, 37.562984),
+ bearing: -96,
+ ),
+ );
+
+ map.on('load', (_) {
+ map.addSource(
+ 'video',
+ VideoSource(
+ urls: [
+ 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4'
+ ],
+ coordinates: [
+ [-122.51596391201019, 37.56238816766053],
+ [-122.51467645168304, 37.56410183312965],
+ [-122.51309394836426, 37.563391708549425],
+ [-122.51423120498657, 37.56161849366671]
+ ],
+ ));
+
+ map.addLayer({'id': 'video', 'type': 'raster', 'source': 'video'});
+ });
+ map.on('click', (_) {
+ final source = map.getSource('video') as VideoSource?;
+ if (isPlaying) {
+ source?.pause();
+ } else {
+ source?.play();
+ }
+ isPlaying = !isPlaying;
+ });
+}
diff --git a/example/video_source/index.html b/example/video_source/index.html
new file mode 100644
index 0000000..802d447
--- /dev/null
+++ b/example/video_source/index.html
@@ -0,0 +1,47 @@
+
+
+
+ Display a video source
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/mapbox_gl_dart.dart b/lib/mapbox_gl_dart.dart
index 955c951..001460c 100644
--- a/lib/mapbox_gl_dart.dart
+++ b/lib/mapbox_gl_dart.dart
@@ -4,6 +4,7 @@
library mapboxgl;
export 'src/geo/geojson.dart';
+export 'src/geo/image_options.dart';
export 'src/geo/lng_lat.dart';
export 'src/geo/lng_lat_bounds.dart';
export 'src/geo/point.dart';
@@ -13,9 +14,12 @@ export 'src/style/layers/circle_layer.dart';
export 'src/style/layers/layer.dart';
export 'src/style/layers/line_layer.dart';
export 'src/style/layers/symbol_layer.dart';
+export 'src/style/sources/canvas_source.dart';
export 'src/style/sources/geojson_source.dart';
+export 'src/style/sources/image_source.dart';
export 'src/style/sources/source.dart';
export 'src/style/sources/vector_source.dart';
+export 'src/style/sources/video_source.dart';
export 'src/style/style.dart';
export 'src/style/style_image.dart';
export 'src/ui/camera.dart';
diff --git a/lib/src/geo/image_options.dart b/lib/src/geo/image_options.dart
new file mode 100644
index 0000000..6b27058
--- /dev/null
+++ b/lib/src/geo/image_options.dart
@@ -0,0 +1,27 @@
+library mapboxgl.geo.image_options;
+
+import 'package:mapbox_gl_dart/src/interop/interop.dart';
+
+class ImageOptions extends JsObjectWrapper {
+ String get url => jsObject.url;
+ dynamic get coordinates => jsObject.coordinates;
+
+ factory ImageOptions({
+ String? url,
+ dynamic coordinates,
+ }) {
+ if (coordinates != null &&
+ (coordinates is! List || coordinates.length != 4)) {
+ throw Exception(
+ 'Image coordinates must be an array of four longitude latitude pairs');
+ }
+ return ImageOptions.fromJsObject(ImageOptionsJsImpl(
+ url: url,
+ coordinates: coordinates,
+ ));
+ }
+
+ /// Creates a new ImageOptions from a [jsObject].
+ ImageOptions.fromJsObject(ImageOptionsJsImpl jsObject)
+ : super.fromJsObject(jsObject);
+}
diff --git a/lib/src/interop/geo/image_options_interop.dart b/lib/src/interop/geo/image_options_interop.dart
new file mode 100644
index 0000000..1c59531
--- /dev/null
+++ b/lib/src/interop/geo/image_options_interop.dart
@@ -0,0 +1,15 @@
+@JS('mapboxgl')
+library mapboxgl.interop.geo.image_options;
+
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ImageOptionsJsImpl {
+ external String get url;
+ external dynamic get coordinates;
+ external factory ImageOptionsJsImpl({
+ String? url,
+ dynamic coordinates,
+ });
+}
diff --git a/lib/src/interop/interop.dart b/lib/src/interop/interop.dart
index 59f8cf0..3a15312 100644
--- a/lib/src/interop/interop.dart
+++ b/lib/src/interop/interop.dart
@@ -1,6 +1,7 @@
library mapboxgl.interop;
export 'geo/geojson_interop.dart';
+export 'geo/image_options_interop.dart';
export 'geo/lng_lat_bounds_interop.dart';
export 'geo/lng_lat_interop.dart';
export 'geo/point_interop.dart';
@@ -9,8 +10,12 @@ export 'style/evaluation_parameters_interop.dart';
export 'style/layers/circle_layer_interop.dart';
export 'style/layers/line_layer_interop.dart';
export 'style/layers/symbol_layer_interop.dart';
+export 'style/sources/canvas_source_interop.dart';
export 'style/sources/geojson_source_interop.dart';
+export 'style/sources/image_source_interop.dart';
+export 'style/sources/image_source_interop.dart';
export 'style/sources/vector_source_interop.dart';
+export 'style/sources/video_source_interop.dart';
export 'style/style_image_interop.dart';
export 'style/style_interop.dart';
export 'ui/camera_interop.dart';
diff --git a/lib/src/interop/style/sources/canvas_source_interop.dart b/lib/src/interop/style/sources/canvas_source_interop.dart
new file mode 100644
index 0000000..303e035
--- /dev/null
+++ b/lib/src/interop/style/sources/canvas_source_interop.dart
@@ -0,0 +1,22 @@
+@JS('mapboxgl')
+library mapboxgl.style.interop.sources.canvas_source;
+
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class CanvasSourceJsImpl {
+ external bool get animate;
+ external String get canvas;
+ external dynamic get coordinates;
+ external factory CanvasSourceJsImpl({
+ String? type,
+ bool? animate = false,
+ String canvas,
+ dynamic coordinates,
+ });
+
+ external CanvasSourceJsImpl play();
+ external CanvasSourceJsImpl pause();
+ external CanvasSourceJsImpl setCoordinates(dynamic coordinates);
+}
diff --git a/lib/src/interop/style/sources/image_source_interop.dart b/lib/src/interop/style/sources/image_source_interop.dart
new file mode 100644
index 0000000..775550e
--- /dev/null
+++ b/lib/src/interop/style/sources/image_source_interop.dart
@@ -0,0 +1,20 @@
+@JS('mapboxgl')
+library mapboxgl.style.interop.sources.image_source;
+
+import 'package:js/js.dart';
+import 'package:mapbox_gl_dart/src/interop/interop.dart';
+
+@JS()
+@anonymous
+class ImageSourceJsImpl {
+ external String get url;
+ external dynamic get coordinates;
+ external factory ImageSourceJsImpl({
+ String? type,
+ String url,
+ dynamic coordinates,
+ });
+
+ external ImageSourceJsImpl updateImage(ImageOptionsJsImpl imageOptions);
+ external ImageSourceJsImpl setCoordinates(dynamic coordinates);
+}
diff --git a/lib/src/interop/style/sources/video_source_interop.dart b/lib/src/interop/style/sources/video_source_interop.dart
new file mode 100644
index 0000000..43f1f03
--- /dev/null
+++ b/lib/src/interop/style/sources/video_source_interop.dart
@@ -0,0 +1,20 @@
+@JS('mapboxgl')
+library mapboxgl.style.interop.sources.video_source;
+
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class VideoSourceJsImpl {
+ external List get urls;
+ external dynamic get coordinates;
+ external factory VideoSourceJsImpl({
+ String? type,
+ List urls,
+ dynamic coordinates,
+ });
+
+ external VideoSourceJsImpl play();
+ external VideoSourceJsImpl pause();
+ external VideoSourceJsImpl setCoordinates(dynamic coordinates);
+}
diff --git a/lib/src/style/sources/canvas_source.dart b/lib/src/style/sources/canvas_source.dart
new file mode 100644
index 0000000..2d4c5d2
--- /dev/null
+++ b/lib/src/style/sources/canvas_source.dart
@@ -0,0 +1,49 @@
+library mapboxgl.style.sources.canvas_source;
+
+import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
+import 'package:mapbox_gl_dart/src/interop/interop.dart';
+
+class CanvasSource extends Source {
+ static const type = 'canvas';
+ bool get animate => jsObject.animate;
+ String get canvas => jsObject.canvas;
+ dynamic get coordinates => jsObject.coordinates;
+
+ factory CanvasSource({
+ required String canvas,
+ bool? animate,
+ required dynamic coordinates,
+ }) {
+ if (coordinates == null) {
+ throw Exception('Specify coordinates');
+ }
+ if ((coordinates as List?)?.length != 4) {
+ throw Exception(
+ 'Coordinates must be an array of four longitude latitude pairs');
+ }
+ return CanvasSource.fromJsObject(CanvasSourceJsImpl(
+ type: type,
+ animate: animate,
+ canvas: canvas,
+ coordinates: coordinates,
+ ));
+ }
+
+ CanvasSource play() => CanvasSource.fromJsObject(jsObject.play());
+
+ CanvasSource pause() => CanvasSource.fromJsObject(jsObject.pause());
+
+ CanvasSource setCoordinates(dynamic coordinates) =>
+ CanvasSource.fromJsObject(jsObject.setCoordinates(coordinates));
+
+ CanvasSource.fromJsObject(CanvasSourceJsImpl jsObject)
+ : super.fromJsObject(jsObject);
+
+ @override
+ get dict => {
+ 'type': type,
+ 'canvas': canvas,
+ 'coordinates': coordinates,
+ 'animate': animate
+ };
+}
diff --git a/lib/src/style/sources/geojson_source.dart b/lib/src/style/sources/geojson_source.dart
index 8725b3b..1273b61 100644
--- a/lib/src/style/sources/geojson_source.dart
+++ b/lib/src/style/sources/geojson_source.dart
@@ -4,6 +4,7 @@ import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
import 'package:mapbox_gl_dart/src/interop/interop.dart';
class GeoJsonSource extends Source {
+ static const type = 'geojson';
FeatureCollection get data => FeatureCollection.fromJsObject(jsObject.data);
String? get promoteId => jsObject.promoteId;
@@ -12,7 +13,7 @@ class GeoJsonSource extends Source {
String? promoteId,
}) =>
GeoJsonSource.fromJsObject(GeoJsonSourceJsImpl(
- type: 'geojson',
+ type: type,
promoteId: promoteId,
data: data.jsObject,
));
@@ -26,7 +27,7 @@ class GeoJsonSource extends Source {
@override
get dict => {
- 'type': 'geojson',
+ 'type': type,
'promoteId': promoteId,
'data': data.jsObject,
};
diff --git a/lib/src/style/sources/image_source.dart b/lib/src/style/sources/image_source.dart
new file mode 100644
index 0000000..b0e1005
--- /dev/null
+++ b/lib/src/style/sources/image_source.dart
@@ -0,0 +1,51 @@
+library mapboxgl.style.sources.image_source;
+
+import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
+import 'package:mapbox_gl_dart/src/interop/interop.dart';
+
+class ImageSource extends Source {
+ static const type = 'image';
+ String? get url => jsObject.url;
+ dynamic get coordinates => jsObject.coordinates;
+
+ factory ImageSource({
+ required String url,
+ dynamic coordinates,
+ }) {
+ if (coordinates == null) {
+ throw Exception('Specify coordinates');
+ }
+ if ((coordinates as List?)?.length != 4) {
+ throw Exception(
+ 'Image coordinates must be an array of four longitude latitude pairs');
+ }
+ return ImageSource.fromJsObject(ImageSourceJsImpl(
+ type: type,
+ url: url,
+ coordinates: coordinates,
+ ));
+ }
+
+ ImageSource updateImage(ImageOptions imageOptions) =>
+ ImageSource.fromJsObject(jsObject.updateImage(imageOptions.jsObject));
+
+ ImageSource setCoordinates(dynamic coordinates) =>
+ ImageSource.fromJsObject(jsObject.setCoordinates(coordinates));
+
+ ImageSource.fromJsObject(ImageSourceJsImpl jsObject)
+ : super.fromJsObject(jsObject);
+
+ @override
+ get dict {
+ Map dict = {
+ 'type': type,
+ };
+ if (url != null) {
+ dict['url'] = url;
+ }
+ if (coordinates != null) {
+ dict['coordinates'] = coordinates;
+ }
+ return dict;
+ }
+}
diff --git a/lib/src/style/sources/vector_source.dart b/lib/src/style/sources/vector_source.dart
index bf84eec..8523576 100644
--- a/lib/src/style/sources/vector_source.dart
+++ b/lib/src/style/sources/vector_source.dart
@@ -4,6 +4,7 @@ import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
import 'package:mapbox_gl_dart/src/interop/interop.dart';
class VectorSource extends Source {
+ static const type = 'vector';
String? get url => jsObject.url;
List? get tiles => jsObject.tiles;
@@ -21,7 +22,7 @@ class VectorSource extends Source {
));
}
return VectorSource.fromJsObject(VectorSourceJsImpl(
- type: 'vector',
+ type: type,
tiles: tiles,
));
}
@@ -33,7 +34,7 @@ class VectorSource extends Source {
@override
get dict {
Map dict = {
- 'type': 'vector',
+ 'type': type,
};
if (url != null) {
dict['url'] = url;
diff --git a/lib/src/style/sources/video_source.dart b/lib/src/style/sources/video_source.dart
new file mode 100644
index 0000000..7cb2955
--- /dev/null
+++ b/lib/src/style/sources/video_source.dart
@@ -0,0 +1,48 @@
+library mapboxgl.style.sources.image_source;
+
+import 'package:mapbox_gl_dart/mapbox_gl_dart.dart';
+import 'package:mapbox_gl_dart/src/interop/interop.dart';
+
+class VideoSource extends Source {
+ static const type = 'video';
+ List get urls => jsObject.urls;
+ dynamic get coordinates => jsObject.coordinates;
+
+ factory VideoSource({
+ required List urls,
+ required dynamic coordinates,
+ }) {
+ if (coordinates == null) {
+ throw Exception('Specify coordinates');
+ }
+ if ((coordinates as List?)?.length != 4) {
+ throw Exception(
+ 'Video coordinates must be an array of four longitude latitude pairs');
+ }
+ if (urls.isEmpty) {
+ throw Exception('Specify at least 1 url');
+ }
+ return VideoSource.fromJsObject(VideoSourceJsImpl(
+ type: type,
+ urls: urls,
+ coordinates: coordinates,
+ ));
+ }
+
+ VideoSource play() => VideoSource.fromJsObject(jsObject.play());
+
+ VideoSource pause() => VideoSource.fromJsObject(jsObject.pause());
+
+ VideoSource setCoordinates(dynamic coordinates) =>
+ VideoSource.fromJsObject(jsObject.setCoordinates(coordinates));
+
+ VideoSource.fromJsObject(VideoSourceJsImpl jsObject)
+ : super.fromJsObject(jsObject);
+
+ @override
+ get dict => {
+ 'type': type,
+ 'urls': urls,
+ 'coordinates': coordinates,
+ };
+}
diff --git a/lib/src/ui/map.dart b/lib/src/ui/map.dart
index ee9f65b..5619a57 100644
--- a/lib/src/ui/map.dart
+++ b/lib/src/ui/map.dart
@@ -584,13 +584,19 @@ class MapboxMap extends Camera {
/// @see [Add live realtime data](https://www.mapbox.com/mapbox-gl-js/example/live-geojson/)
dynamic getSource(String id) {
var source = jsObject.getSource(id);
- if (source is GeoJsonSourceJsImpl) {
- return GeoJsonSource.fromJsObject(source);
+ switch (source?.type) {
+ case ImageSource.type:
+ if (source?.canvas != null) {
+ return CanvasSource.fromJsObject(source);
+ }
+ return ImageSource.fromJsObject(source);
+ case VectorSource.type:
+ return VectorSource.fromJsObject(source);
+ case VideoSource.type:
+ return VideoSource.fromJsObject(source);
+ default:
+ return GeoJsonSource.fromJsObject(source);
}
- if (source is VectorSourceJsImpl) {
- return VectorSource.fromJsObject(source);
- }
- return source;
}
/// Add an image to the style. This image can be displayed on the map like any other icon in the style's
diff --git a/pubspec.yaml b/pubspec.yaml
index 3b9c471..133d229 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: mapbox_gl_dart
-version: 0.2.1
+version: 0.2.2
description: Mapbox-gl wrapper for Dart. Library to use Mapbox GL JS in your web Dart projects.
homepage: https://github.com/andrea689/mapbox-gl-dart/
environment: