Skip to content

Commit

Permalink
line annotations in dart
Browse files Browse the repository at this point in the history
  • Loading branch information
felix-ht committed Nov 19, 2021
1 parent b26debb commit a0459dd
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 34 deletions.
44 changes: 19 additions & 25 deletions example/lib/line.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@ class LineBodyState extends State<LineBody> {
static final LatLng center = const LatLng(-33.86711, 151.1947171);

MapboxMapController? controller;
LineManager? lineManager;
int lineId = 0;

int _lineCount = 0;
Line? _selectedLine;

void _onMapCreated(MapboxMapController controller) {
this.controller = controller;
controller.onLineTapped.add(_onLineTapped);
}

@override
void dispose() {
controller?.onLineTapped.remove(_onLineTapped);
super.dispose();
}

Expand All @@ -57,19 +58,17 @@ class LineBodyState extends State<LineBody> {
setState(() {
_selectedLine = line;
});
_updateSelectedLine(
LineOptions(
// linecolor: ,
),
);
}

void _updateSelectedLine(LineOptions changes) {
controller!.updateLine(_selectedLine!, changes);
_selectedLine = _selectedLine!
.copyWith(options: _selectedLine!.options.copyWith(changes));
lineManager!.set(_selectedLine!);
}

void _add() {
controller!.addLine(
lineManager!.add(Line(
lineId.toString(),
LineOptions(
geometry: [
LatLng(-33.86711, 151.1947171),
Expand All @@ -78,17 +77,19 @@ class LineBodyState extends State<LineBody> {
LatLng(-33.86711, 152.1947171),
],
lineColor: "#ff0000",
lineWidth: 14.0,
lineWidth: 30.0,
lineOpacity: 0.5,
draggable: true),
);
));

setState(() {
lineId++;
_lineCount += 1;
});
}

void _remove() {
controller!.removeLine(_selectedLine!);
lineManager!.remove(_selectedLine!);
setState(() {
_selectedLine = null;
_lineCount -= 1;
Expand Down Expand Up @@ -119,14 +120,7 @@ class LineBodyState extends State<LineBody> {
}

void onStyleLoadedCallback() {
controller!.addLine(
LineOptions(
geometry: [LatLng(37.4220, -122.0841), LatLng(37.4240, -122.0941)],
lineColor: "#ff0000",
lineWidth: 14.0,
lineOpacity: 0.5,
),
);
lineManager = LineManager(controller!, onTap: _onLineTapped);
}

@override
Expand All @@ -137,8 +131,7 @@ class LineBodyState extends State<LineBody> {
children: <Widget>[
Center(
child: SizedBox(
width: 300.0,
height: 200.0,
height: 300.0,
child: MapboxMap(
accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
Expand Down Expand Up @@ -186,9 +179,10 @@ class LineBodyState extends State<LineBody> {
onPressed: (_selectedLine == null)
? null
: () async {
var latLngs = await controller!
.getLineLatLngs(_selectedLine!);
for (var latLng in latLngs) {
var current =
lineManager!.byId(_selectedLine!.id)!;
for (var latLng
in current.options.geometry!) {
print(latLng.toString());
}
},
Expand Down
3 changes: 3 additions & 0 deletions lib/mapbox_gl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart'
MyLocationRenderMode,
CompassViewPosition,
AttributionButtonPosition,
Annotation,
Circle,
CircleOptions,
Line,
Expand All @@ -49,3 +50,5 @@ part 'src/download_region_status.dart';
part 'src/layer_expressions.dart';
part 'src/layer_properties.dart';
part 'src/color_tools.dart';
part 'src/annotation.dart';
part 'src/util.dart';
101 changes: 101 additions & 0 deletions lib/src/annotation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
part of mapbox_gl;

abstract class _AnnotationManager<T extends Annotation> {
final MapboxMapController controller;
final void Function(T)? onTap;
final _idToAnnotation = <String, T>{};
final id;
LatLng? _dragOrigin;
LayerProperties get properties;

T? byId(String id) => _idToAnnotation[id];

_AnnotationManager(this.controller, {this.onTap}) : id = getRandomString(10) {
controller.addGeoJsonSource(id, buildFeatureCollection([]));
controller.addLayer(id, id, properties);
if (onTap != null) {
controller.onFeatureTapped.add(_onFeatureTapped);
}
}
_onFeatureTapped(id) {
final annotation = _idToAnnotation[id];
if (annotation != null) {
onTap!(annotation);
}
}

Future<void> _setAll() async {
return controller.setGeoJsonSource(
id,
buildFeatureCollection(
[for (final l in _idToAnnotation.values) l.toGeoJson()]));
}

Future<void> addAll(Iterable<T> annotations) async {
for (var a in annotations) {
_idToAnnotation[a.id] = a;
}
await _setAll();
}

Future<void> add(T annotation) async {
_idToAnnotation[annotation.id] = annotation;
await _setAll();
}

Future<void> remove(T annotation) async {
_idToAnnotation.remove(annotation.id);
await _setAll();
}

Future<void> clear() async {
_idToAnnotation.clear();

await _setAll();
}

// TODO this requires a new call back
onPointerDown(String id, LatLng position) {
final annotation = byId(id);
if (annotation != null && annotation.draggable) {
if (_dragOrigin == null) {
// TODO missing from native !!
//controller.lockCamera();
_dragOrigin = position;
} else {
final moved = annotation.translate(position - _dragOrigin!) as T;
set(moved);
}
}
}

// TODO this requires a new call back
onPointerUp(String id, LatLng position) {
final annotation = byId(id);
if (annotation != null) {
final moved = annotation.translate(position - _dragOrigin!) as T;
set(moved);
}
_dragOrigin = null;
}

Future<void> set(T annoation) async {
_idToAnnotation[annoation.id] = annoation;
//Todo: send only the changed line to plugin
await _setAll();
}
}

class LineManager extends _AnnotationManager<Line> {
LineManager(MapboxMapController controller, {void Function(Line)? onTap})
: super(controller, onTap: onTap);
@override
LayerProperties get properties => const LineLayerProperties(
lineOpacity: [Expressions.get, 'lineOpacity'],
lineColor: [Expressions.get, 'lineColor'],
lineWidth: [Expressions.get, 'lineWidth'],
lineGapWidth: [Expressions.get, 'lineGapWidth'],
lineOffset: [Expressions.get, 'lineOffset'],
lineBlur: [Expressions.get, 'lineBlur'],
);
}
22 changes: 15 additions & 7 deletions lib/src/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,20 @@ class MapboxMapController extends ChangeNotifier {
);
}

Future<void> addLayer(
String sourceId, String layerId, LayerProperties properties,
{String? belowLayerId}) async {
if (properties is FillLayerProperties) {
addFillLayer(sourceId, layerId, properties);
} else if (properties is LineLayerProperties) {
addLineLayer(sourceId, layerId, properties);
} else if (properties is SymbolLayerProperties) {
addSymbolLayer(sourceId, layerId, properties);
} else if (properties is CircleLayerProperties) {
addCircleLayer(sourceId, layerId, properties);
}
}

/// Updates user location tracking mode.
///
/// The returned [Future] completes after the change has been made on the
Expand Down Expand Up @@ -571,7 +585,7 @@ class MapboxMapController extends ChangeNotifier {
Future<void> updateLine(Line line, LineOptions changes) async {
assert(_lines[line.id] == line);
await _mapboxGlPlatform.updateLine(line, changes);
line.options = line.options.copyWith(changes);
_lines[line.id] = line.copyWith(options: line.options.copyWith(changes));
notifyListeners();
}

Expand Down Expand Up @@ -934,12 +948,6 @@ class MapboxMapController extends ChangeNotifier {
return _mapboxGlPlatform.addLayerBelow(layerId, sourceId, imageSourceId);
}

/// Adds a Mapbox image layer to the map's style at render time. Only works for image sources!
@Deprecated("This method was renamed to addImageLayer for clarity.")
Future<void> addLayer(String imageLayerId, String imageSourceId) {
return _mapboxGlPlatform.addLayer(imageLayerId, imageSourceId);
}

/// Adds a Mapbox image layer below the layer provided with belowLayerId to the map's style at render time. Only works for image sources!
@Deprecated("This method was renamed to addImageLayerBelow for clarity.")
Future<void> addLayerBelow(
Expand Down
14 changes: 14 additions & 0 deletions lib/src/util.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
part of mapbox_gl;

Map<String, dynamic> buildFeatureCollection(
List<Map<String, dynamic>> features) {
return {"type": "FeatureCollection", "features": features};
}

final _random = Random();
String getRandomString([int length = 10]) {
const charSet =
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
return String.fromCharCodes(Iterable.generate(
length, (_) => charSet.codeUnitAt(_random.nextInt(charSet.length))));
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show visibleForTesting;

part 'src/annotation.dart';
part 'src/callbacks.dart';
part 'src/camera.dart';
part 'src/circle.dart';
Expand Down
9 changes: 9 additions & 0 deletions mapbox_gl_platform_interface/lib/src/annotation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
part of mapbox_gl_platform_interface;

abstract class Annotation {
String get id;
Map<String, dynamic> toGeoJson();

Annotation translate(LatLng delta);
bool get draggable;
}
50 changes: 48 additions & 2 deletions mapbox_gl_platform_interface/lib/src/line.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

part of mapbox_gl_platform_interface;

class Line {
class Line implements Annotation {
Line(this._id, this.options, [this._data]);

/// A unique identifier for this line.
Expand All @@ -25,7 +25,32 @@ class Line {
///
/// The returned value does not reflect any changes made to the line through
/// touch events. Add listeners to the owning map controller to track those.
LineOptions options;
final LineOptions options;

Line copyWith({String? id, Map? data, LineOptions? options}) {
return Line(
id ?? this.id,
options ?? this.options,
data ?? this.data,
);
}

Map<String, dynamic> toGeoJson() {
final geojson = options.toGeoJson();
geojson["id"] = id;

return geojson;
}

@override
Line translate(LatLng delta) {
final options = this.options.copyWith(LineOptions(
geometry: this.options.geometry?.map((e) => e + delta).toList()));
return copyWith(options: options);
}

@override
bool get draggable => options.draggable ?? false;
}

/// Configuration options for [Line] instances.
Expand Down Expand Up @@ -100,4 +125,25 @@ class LineOptions {
addIfPresent('draggable', draggable);
return json;
}

Map<String, dynamic> toGeoJson() {
return {
"type": "Feature",
"properties": {
if (lineJoin != null) "lineJoin": lineJoin,
if (lineOpacity != null) "lineOpacity": lineOpacity,
if (lineColor != null) "lineColor": lineColor,
if (lineWidth != null) "lineWidth": lineWidth,
if (lineGapWidth != null) "lineGapWidth": lineGapWidth,
if (lineOffset != null) "lineOffset": lineOffset,
if (lineBlur != null) "lineBlur": lineBlur,
if (linePattern != null) "linePattern": linePattern,
},
"geometry": {
"type": "LineString",
if (geometry != null)
"coordinates": geometry?.map((c) => c.toGeoJsonCoordinates()).toList()
}
};
}
}
4 changes: 4 additions & 0 deletions mapbox_gl_platform_interface/lib/src/location.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class LatLng {
return <double>[latitude, longitude];
}

dynamic toGeoJsonCoordinates() {
return <double>[longitude, latitude];
}

static LatLng _fromJson(List<dynamic> json) {
return LatLng(json[0], json[1]);
}
Expand Down

0 comments on commit a0459dd

Please sign in to comment.