feat: partial broken guesture detection
This commit is contained in:
parent
be359980bb
commit
b7487fc25e
2293
assets/geo/uulm_beta copy.geojson
Normal file
2293
assets/geo/uulm_beta copy.geojson
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,6 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
@ -7,7 +9,7 @@ import 'package:uninav/data/geo/model.dart';
|
|||||||
import 'package:uninav/map.dart';
|
import 'package:uninav/map.dart';
|
||||||
import 'package:uninav/util/geomath.dart';
|
import 'package:uninav/util/geomath.dart';
|
||||||
|
|
||||||
List<Widget> renderLevel(int level) {
|
List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
|
||||||
return <Widget>[
|
return <Widget>[
|
||||||
LevelLayer(
|
LevelLayer(
|
||||||
filter: (feature) =>
|
filter: (feature) =>
|
||||||
@ -18,55 +20,58 @@ List<Widget> renderLevel(int level) {
|
|||||||
points: pts,
|
points: pts,
|
||||||
color: Colors.orange.withOpacity(0.2),
|
color: Colors.orange.withOpacity(0.2),
|
||||||
borderColor: Colors.orange,
|
borderColor: Colors.orange,
|
||||||
isFilled: true,
|
borderStrokeWidth: 2,
|
||||||
borderStrokeWidth: 1,
|
hitValue: feature,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
markerConstructor: (feature) => Marker(
|
markerConstructor: (feature) => Marker(
|
||||||
width: 150,
|
width: 50,
|
||||||
height: 60,
|
height: 20,
|
||||||
point: feature.getPoint().unwrap(),
|
point: feature.getPoint().unwrap(),
|
||||||
builder: (cx) => Center(
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
Icon(
|
||||||
Icon(
|
Icons.class_,
|
||||||
Icons.class_,
|
color: Colors.black,
|
||||||
color: Colors.black,
|
),
|
||||||
),
|
Text('${feature.name}'),
|
||||||
Text('${feature.name}'),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)),
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
notifier: hitNotifier),
|
||||||
LevelLayer(
|
LevelLayer(
|
||||||
filter: (feature) => feature.level == level && feature.type is Room,
|
filter: (feature) => feature.level == level && feature.type is Room,
|
||||||
polyConstructor: (feature) => feature
|
polyConstructor: (feature) => feature
|
||||||
.getPolygon(
|
.getPolygon(
|
||||||
constructor: (pts) => Polygon(
|
constructor: (pts) => Polygon(
|
||||||
points: pts,
|
points: pts,
|
||||||
color: Colors.green.withOpacity(0.2),
|
color: Colors.green.withOpacity(1.2),
|
||||||
borderColor: Colors.green,
|
borderColor: Colors.green,
|
||||||
isFilled: true,
|
borderStrokeWidth: 2,
|
||||||
borderStrokeWidth: 1,
|
hitValue: feature,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
notifier: hitNotifier,
|
||||||
),
|
),
|
||||||
LevelLayer(
|
LevelLayer(
|
||||||
filter: (feature) => feature.level == level && feature.type is Door,
|
filter: (feature) => feature.level == level && feature.type is Door,
|
||||||
markerConstructor: (feature) {
|
markerConstructor: (feature) {
|
||||||
final point = feature.getPoint().unwrap();
|
final point = feature.getPoint().unwrap();
|
||||||
return Marker(
|
return Marker(
|
||||||
width: 20,
|
width: 21,
|
||||||
height: 20,
|
height: 21,
|
||||||
point: point,
|
point: point,
|
||||||
builder: (ctx) => const Icon(
|
child: const Icon(
|
||||||
Icons.door_front_door,
|
Icons.door_front_door,
|
||||||
color: Colors.brown,
|
color: Colors.brown,
|
||||||
),
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
notifier: hitNotifier,
|
||||||
),
|
),
|
||||||
LevelLayer(
|
LevelLayer(
|
||||||
filter: (feature) => feature.level == level && feature.type is Toilet,
|
filter: (feature) => feature.level == level && feature.type is Toilet,
|
||||||
@ -93,16 +98,17 @@ List<Widget> renderLevel(int level) {
|
|||||||
|
|
||||||
final point = feature.getPoint().unwrap();
|
final point = feature.getPoint().unwrap();
|
||||||
return Marker(
|
return Marker(
|
||||||
width: 20,
|
width: 21,
|
||||||
height: 20,
|
height: 21,
|
||||||
point: point,
|
point: point,
|
||||||
builder: (ctx) => Icon(
|
child: Icon(
|
||||||
icon,
|
icon,
|
||||||
color: Colors.purple,
|
color: Colors.purple,
|
||||||
),
|
),
|
||||||
rotateAlignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
notifier: hitNotifier,
|
||||||
),
|
),
|
||||||
LevelLayer(
|
LevelLayer(
|
||||||
filter: (feature) =>
|
filter: (feature) =>
|
||||||
@ -111,15 +117,17 @@ List<Widget> renderLevel(int level) {
|
|||||||
markerConstructor: (feature) {
|
markerConstructor: (feature) {
|
||||||
final point = feature.getPoint().unwrap();
|
final point = feature.getPoint().unwrap();
|
||||||
return Marker(
|
return Marker(
|
||||||
width: 20,
|
width: 21,
|
||||||
height: 20,
|
height: 21,
|
||||||
point: point,
|
point: point,
|
||||||
builder: (ctx) => Icon(
|
child: Icon(
|
||||||
Icons.stairs_outlined,
|
Icons.stairs_outlined,
|
||||||
color: Colors.deepPurple.shade300,
|
color: Colors.deepPurple.shade300,
|
||||||
),
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
notifier: hitNotifier,
|
||||||
),
|
),
|
||||||
LevelLayer(
|
LevelLayer(
|
||||||
filter: (feature) =>
|
filter: (feature) =>
|
||||||
@ -128,15 +136,17 @@ List<Widget> renderLevel(int level) {
|
|||||||
markerConstructor: (feature) {
|
markerConstructor: (feature) {
|
||||||
final point = feature.getPoint().unwrap();
|
final point = feature.getPoint().unwrap();
|
||||||
return Marker(
|
return Marker(
|
||||||
width: 20,
|
width: 21,
|
||||||
height: 20,
|
height: 21,
|
||||||
point: point,
|
point: point,
|
||||||
builder: (ctx) => const Icon(
|
child: const Icon(
|
||||||
Icons.elevator_outlined,
|
Icons.elevator_outlined,
|
||||||
color: Colors.deepPurple,
|
color: Colors.deepPurple,
|
||||||
),
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
notifier: hitNotifier,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -147,6 +157,7 @@ class LevelLayer extends StatelessWidget {
|
|||||||
final Marker Function(LatLng, String)? polyCenterMarkerConstructor;
|
final Marker Function(LatLng, String)? polyCenterMarkerConstructor;
|
||||||
final Marker Function(Feature)? markerConstructor;
|
final Marker Function(Feature)? markerConstructor;
|
||||||
final int? level;
|
final int? level;
|
||||||
|
final LayerHitNotifier? notifier;
|
||||||
|
|
||||||
const LevelLayer({
|
const LevelLayer({
|
||||||
this.level,
|
this.level,
|
||||||
@ -154,6 +165,7 @@ class LevelLayer extends StatelessWidget {
|
|||||||
this.polyConstructor,
|
this.polyConstructor,
|
||||||
this.polyCenterMarkerConstructor,
|
this.polyCenterMarkerConstructor,
|
||||||
this.markerConstructor,
|
this.markerConstructor,
|
||||||
|
this.notifier,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -172,7 +184,15 @@ class LevelLayer extends StatelessWidget {
|
|||||||
if (polyConstructor != null) {
|
if (polyConstructor != null) {
|
||||||
filteredPolygons.add(polyConstructor!(feature));
|
filteredPolygons.add(polyConstructor!(feature));
|
||||||
} else {
|
} else {
|
||||||
filteredPolygons.add(feature.getPolygon().unwrap());
|
filteredPolygons.add(feature
|
||||||
|
.getPolygon(
|
||||||
|
constructor: (points) => Polygon(
|
||||||
|
points: points,
|
||||||
|
borderColor: Colors.black26,
|
||||||
|
borderStrokeWidth: 2.0,
|
||||||
|
hitValue: feature,
|
||||||
|
))
|
||||||
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate polygon center
|
// calculate polygon center
|
||||||
@ -186,7 +206,7 @@ class LevelLayer extends StatelessWidget {
|
|||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
point: center,
|
point: center,
|
||||||
builder: (cx) => Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
feature.name,
|
feature.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
@ -195,6 +215,7 @@ class LevelLayer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else if (feature.isPoint()) {
|
} else if (feature.isPoint()) {
|
||||||
@ -206,7 +227,7 @@ class LevelLayer extends StatelessWidget {
|
|||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
point: point,
|
point: point,
|
||||||
builder: (cx) => Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
feature.name,
|
feature.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
@ -215,6 +236,7 @@ class LevelLayer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,28 +248,39 @@ class LevelLayer extends StatelessWidget {
|
|||||||
// print(filteredPolygons[0].points[0]);
|
// print(filteredPolygons[0].points[0]);
|
||||||
// print(myMapController.features.length);
|
// print(myMapController.features.length);
|
||||||
|
|
||||||
|
// filteredPolygons.forEach((element) {
|
||||||
|
// print(element.hitValue);
|
||||||
|
// });
|
||||||
|
|
||||||
final List<Widget> widgets = [];
|
final List<Widget> widgets = [];
|
||||||
if (filteredPolygons.isNotEmpty) {
|
if (filteredPolygons.isNotEmpty) {
|
||||||
if (polyConstructor != null) {
|
if (polyConstructor != null) {
|
||||||
widgets.add(PolygonLayer(polygons: filteredPolygons));
|
widgets.add(TranslucentPointer(
|
||||||
|
child: PolygonLayer(
|
||||||
|
polygons: filteredPolygons,
|
||||||
|
hitNotifier: notifier,
|
||||||
|
),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
widgets.add(PolygonLayer(
|
widgets.add(TranslucentPointer(
|
||||||
polygons: filteredPolygons
|
child: PolygonLayer(
|
||||||
.map((poly) => Polygon(
|
polygons: filteredPolygons,
|
||||||
points: poly.points,
|
hitNotifier: notifier,
|
||||||
borderColor: Colors.black26,
|
),
|
||||||
borderStrokeWidth: 2.0,
|
));
|
||||||
))
|
|
||||||
.toList()));
|
|
||||||
}
|
}
|
||||||
widgets.add(MarkerLayer(
|
widgets.add(TranslucentPointer(
|
||||||
markers: polygonCenterMarkers,
|
child: MarkerLayer(
|
||||||
rotate: true,
|
markers: polygonCenterMarkers,
|
||||||
|
rotate: true,
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filteredMarkers.isNotEmpty) {
|
if (filteredMarkers.isNotEmpty) {
|
||||||
widgets.add(MarkerLayer(markers: filteredMarkers, rotate: true));
|
widgets.add(TranslucentPointer(
|
||||||
|
child: MarkerLayer(markers: filteredMarkers, rotate: true),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Stack(children: widgets);
|
return Stack(children: widgets);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:anyhow/anyhow.dart';
|
import 'package:anyhow/anyhow.dart';
|
||||||
import 'package:geojson/geojson.dart';
|
import 'package:geojson_vi/geojson_vi.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:uninav/data/geo/model.dart';
|
import 'package:uninav/data/geo/model.dart';
|
||||||
import 'package:uninav/data/geo/parser.dart';
|
import 'package:uninav/data/geo/parser.dart';
|
||||||
@ -46,14 +46,17 @@ class MyMapController extends GetxController {
|
|||||||
|
|
||||||
final featuresList = <Feature>[];
|
final featuresList = <Feature>[];
|
||||||
|
|
||||||
final geojson = GeoJson();
|
print('doing');
|
||||||
|
final geojson = GeoJSONFeatureCollection.fromJSON(geoJsonString);
|
||||||
await geojson.parse(geoJsonString);
|
print('done');
|
||||||
|
|
||||||
for (final feature in geojson.features) {
|
for (final feature in geojson.features) {
|
||||||
|
print(feature);
|
||||||
|
print(feature?.properties);
|
||||||
|
if (feature == null) continue;
|
||||||
print(feature.properties);
|
print(feature.properties);
|
||||||
final parsed =
|
final parsed = parseFeature(
|
||||||
parseFeature(feature.properties ?? <String, dynamic>{}, feature);
|
feature.properties ?? <String, dynamic>{}, feature.geometry);
|
||||||
if (parsed case Ok(:final ok)) {
|
if (parsed case Ok(:final ok)) {
|
||||||
featuresList.add(ok);
|
featuresList.add(ok);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import 'package:anyhow/anyhow.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:geojson/geojson.dart';
|
import 'package:geojson_vi/geojson_vi.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
part 'model.freezed.dart';
|
part 'model.freezed.dart';
|
||||||
@ -15,27 +15,30 @@ class Feature with _$Feature {
|
|||||||
required String name,
|
required String name,
|
||||||
required FeatureType type,
|
required FeatureType type,
|
||||||
String? description,
|
String? description,
|
||||||
required dynamic geometry,
|
required GeoJSONGeometry geometry,
|
||||||
int? level,
|
int? level,
|
||||||
}) = _Feature;
|
}) = _Feature;
|
||||||
|
|
||||||
bool isPolygon() {
|
bool isPolygon() {
|
||||||
return geometry is GeoJsonFeature<GeoJsonPolygon>;
|
return geometry is GeoJSONPolygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPoint() {
|
bool isPoint() {
|
||||||
return geometry is GeoJsonFeature<GeoJsonPoint>;
|
return geometry is GeoJSONPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Polygon> getPolygon({Polygon Function(List<LatLng>)? constructor}) {
|
Result<Polygon> getPolygon({Polygon Function(List<LatLng>)? constructor}) {
|
||||||
if (isPolygon()) {
|
if (isPolygon()) {
|
||||||
constructor ??= (pts) => Polygon(
|
constructor ??= (pts) => Polygon(
|
||||||
points: pts, borderColor: Colors.black26, borderStrokeWidth: 2.0);
|
points: pts,
|
||||||
final polygon = geometry as GeoJsonFeature<GeoJsonPolygon>;
|
borderColor: Colors.black26,
|
||||||
|
borderStrokeWidth: 2.0,
|
||||||
|
);
|
||||||
|
final polygon = geometry as GeoJSONPolygon;
|
||||||
// print(polygon.geometry!.geoSeries[0].geoPoints);
|
// print(polygon.geometry!.geoSeries[0].geoPoints);
|
||||||
final points = polygon.geometry!.geoSeries[0].geoPoints
|
final points =
|
||||||
.map((e) => LatLng(e.latitude, e.longitude))
|
// polygon.coordinates[0].map((e) => LatLng(e[0], e[1])).toList();
|
||||||
.toList();
|
polygon.coordinates[0].map((e) => LatLng(e[1], e[0])).toList();
|
||||||
|
|
||||||
// print(points);
|
// print(points);
|
||||||
return Ok(constructor(points));
|
return Ok(constructor(points));
|
||||||
@ -46,9 +49,8 @@ class Feature with _$Feature {
|
|||||||
|
|
||||||
Result<LatLng> getPoint() {
|
Result<LatLng> getPoint() {
|
||||||
if (isPoint()) {
|
if (isPoint()) {
|
||||||
final point = geometry as GeoJsonFeature<GeoJsonPoint>;
|
final point = geometry as GeoJSONPoint;
|
||||||
return Ok(LatLng(point.geometry!.geoPoint.latitude,
|
return Ok(LatLng(point.coordinates[1], point.coordinates[0]));
|
||||||
point.geometry!.geoPoint.longitude));
|
|
||||||
} else {
|
} else {
|
||||||
return bail("Feature Geometry is not a Point");
|
return bail("Feature Geometry is not a Point");
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:anyhow/anyhow.dart';
|
import 'package:anyhow/anyhow.dart';
|
||||||
import 'package:geojson/geojson.dart';
|
import 'package:geojson_vi/geojson_vi.dart';
|
||||||
import 'package:uninav/data/geo/model.dart';
|
import 'package:uninav/data/geo/model.dart';
|
||||||
import 'package:yaml/yaml.dart';
|
import 'package:yaml/yaml.dart';
|
||||||
|
|
||||||
Result<Feature> parseFeature(
|
Result<Feature> parseFeature(
|
||||||
Map<String, dynamic> properties, dynamic geometry) {
|
Map<String, dynamic> properties, GeoJSONGeometry geometry) {
|
||||||
final name = properties['name'] as String?;
|
final name = properties['name'] as String?;
|
||||||
final description_yaml = properties['description'] as String? ?? '';
|
final description_yaml = properties['description'] as String? ?? '';
|
||||||
final layer = properties['layer'] as String?;
|
final layer = properties['layer'] as String?;
|
||||||
|
372
lib/map.dart
372
lib/map.dart
@ -2,12 +2,12 @@ import 'package:anim_search_bar/anim_search_bar.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
import 'package:flutter_map/plugin_api.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
import 'package:rust_core/slice.dart';
|
import 'package:rust_core/slice.dart';
|
||||||
import 'package:uninav/components/drawer.dart';
|
import 'package:uninav/components/drawer.dart';
|
||||||
import 'package:uninav/components/hamburger_menu.dart';
|
import 'package:uninav/components/hamburger_menu.dart';
|
||||||
|
import 'package:uninav/components/map_render_level.dart';
|
||||||
import 'package:uninav/controllers/map_controller.dart';
|
import 'package:uninav/controllers/map_controller.dart';
|
||||||
import 'package:uninav/data/geo/model.dart';
|
import 'package:uninav/data/geo/model.dart';
|
||||||
import 'package:uninav/util/geomath.dart';
|
import 'package:uninav/util/geomath.dart';
|
||||||
@ -18,6 +18,7 @@ class MapPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final LayerHitNotifier hitNotifier = ValueNotifier(null);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
drawer: MyDrawer(),
|
drawer: MyDrawer(),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -51,64 +52,95 @@ class MapPage extends StatelessWidget {
|
|||||||
FlutterMap(
|
FlutterMap(
|
||||||
mapController: MapController(),
|
mapController: MapController(),
|
||||||
options: MapOptions(
|
options: MapOptions(
|
||||||
center: LatLng(48.422766, 9.9564),
|
initialCenter: const LatLng(48.422766, 9.9564),
|
||||||
zoom: 16.0,
|
initialZoom: 16.0,
|
||||||
// camera constraints
|
// camera constraints
|
||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
|
onTap: (tapPosition, latlng) => print(tapPosition),
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
TileLayer(
|
TileLayer(
|
||||||
urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
),
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
print("tap");
|
||||||
|
final LayerHitResult? hit = hitNotifier.value;
|
||||||
|
if (hit == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// buildings
|
print("not null");
|
||||||
LevelLayer(
|
print(hit.coordinate);
|
||||||
filter: (feature) => feature.type is Building,
|
hit.printInfo();
|
||||||
),
|
print(hit.hitValues);
|
||||||
|
|
||||||
// public transport
|
for (final hitValue in hit.hitValues) {
|
||||||
LevelLayer(
|
print(hitValue);
|
||||||
filter: (feature) =>
|
}
|
||||||
feature.level == null && feature.type is PublicTransport,
|
// Handle the hit, which in this case is a tap
|
||||||
polyCenterMarkerConstructor: (center, name) => Marker(
|
// For example, see the example in Hit Handling (below)
|
||||||
width: 100,
|
},
|
||||||
height: 100,
|
child: MouseRegion(
|
||||||
point: center,
|
cursor: SystemMouseCursors.click,
|
||||||
builder: (cx) => const Center(
|
child: Stack(
|
||||||
child: Icon(
|
children: [
|
||||||
Icons.train,
|
// buildings
|
||||||
color: Colors.black,
|
LevelLayer(
|
||||||
),
|
filter: (feature) => feature.type is Building,
|
||||||
|
notifier: hitNotifier,
|
||||||
|
),
|
||||||
|
|
||||||
|
// public transport
|
||||||
|
LevelLayer(
|
||||||
|
filter: (feature) =>
|
||||||
|
feature.level == null &&
|
||||||
|
feature.type is PublicTransport,
|
||||||
|
polyCenterMarkerConstructor: (center, name) => Marker(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
point: center,
|
||||||
|
child: const Icon(
|
||||||
|
Icons.train,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
polyConstructor: (feature) => feature
|
||||||
|
.getPolygon(
|
||||||
|
constructor: (pts) => Polygon(
|
||||||
|
points: pts,
|
||||||
|
color: Colors.green.withOpacity(0.2),
|
||||||
|
borderColor: Colors.green,
|
||||||
|
borderStrokeWidth: 1,
|
||||||
|
hitValue: feature,
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
|
notifier: hitNotifier,
|
||||||
|
),
|
||||||
|
|
||||||
|
// current level
|
||||||
|
Obx(
|
||||||
|
() => Stack(
|
||||||
|
children: renderLevel(
|
||||||
|
Get.find<MyMapController>()
|
||||||
|
.currentLevel
|
||||||
|
.value,
|
||||||
|
hitNotifier: hitNotifier)),
|
||||||
|
),
|
||||||
|
|
||||||
|
// RichAttributionWidget(attributions: [
|
||||||
|
// TextSourceAttribution(
|
||||||
|
// 'OpenStreetMap contributors',
|
||||||
|
// onTap: () =>
|
||||||
|
// launchUrl(Uri.parse('https://openstreetmap.org/copyright')),
|
||||||
|
// )
|
||||||
|
// ]),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
polyConstructor: (feature) => feature
|
|
||||||
.getPolygon(
|
|
||||||
constructor: (pts) => Polygon(
|
|
||||||
points: pts,
|
|
||||||
color: Colors.green.withOpacity(0.2),
|
|
||||||
borderColor: Colors.green,
|
|
||||||
isFilled: true,
|
|
||||||
borderStrokeWidth: 1,
|
|
||||||
))
|
|
||||||
.unwrap(),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
// current level
|
|
||||||
Obx(
|
|
||||||
() => Stack(
|
|
||||||
children: renderLevel(
|
|
||||||
Get.find<MyMapController>().currentLevel.value),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// RichAttributionWidget(attributions: [
|
|
||||||
// TextSourceAttribution(
|
|
||||||
// 'OpenStreetMap contributors',
|
|
||||||
// onTap: () =>
|
|
||||||
// launchUrl(Uri.parse('https://openstreetmap.org/copyright')),
|
|
||||||
// )
|
|
||||||
// ]),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
@ -152,251 +184,3 @@ class MapPage extends StatelessWidget {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> renderLevel(int level) {
|
|
||||||
return <Widget>[
|
|
||||||
LevelLayer(
|
|
||||||
filter: (feature) =>
|
|
||||||
feature.level == level && feature.type is LectureHall,
|
|
||||||
polyConstructor: (feature) => feature
|
|
||||||
.getPolygon(
|
|
||||||
constructor: (pts) => Polygon(
|
|
||||||
points: pts,
|
|
||||||
color: Colors.orange.withOpacity(0.2),
|
|
||||||
borderColor: Colors.orange,
|
|
||||||
isFilled: true,
|
|
||||||
borderStrokeWidth: 1,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
markerConstructor: (feature) => Marker(
|
|
||||||
width: 150,
|
|
||||||
height: 60,
|
|
||||||
point: feature.getPoint().unwrap(),
|
|
||||||
builder: (cx) => Center(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.class_,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
Text('${feature.name}'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
LevelLayer(
|
|
||||||
filter: (feature) => feature.level == level && feature.type is Room,
|
|
||||||
polyConstructor: (feature) => feature
|
|
||||||
.getPolygon(
|
|
||||||
constructor: (pts) => Polygon(
|
|
||||||
points: pts,
|
|
||||||
color: Colors.green.withOpacity(0.2),
|
|
||||||
borderColor: Colors.green,
|
|
||||||
isFilled: true,
|
|
||||||
borderStrokeWidth: 1,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
LevelLayer(
|
|
||||||
filter: (feature) => feature.level == level && feature.type is Door,
|
|
||||||
markerConstructor: (feature) {
|
|
||||||
final point = feature.getPoint().unwrap();
|
|
||||||
return Marker(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
point: point,
|
|
||||||
builder: (ctx) => const Icon(
|
|
||||||
Icons.door_front_door,
|
|
||||||
color: Colors.brown,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
LevelLayer(
|
|
||||||
filter: (feature) => feature.level == level && feature.type is Toilet,
|
|
||||||
markerConstructor: (feature) {
|
|
||||||
final type = (feature.type as Toilet).toilet_type;
|
|
||||||
IconData icon;
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case 'male':
|
|
||||||
icon = Icons.male;
|
|
||||||
break;
|
|
||||||
case 'female':
|
|
||||||
icon = Icons.female;
|
|
||||||
break;
|
|
||||||
case 'handicap':
|
|
||||||
icon = Icons.wheelchair_pickup;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print("WARN: Toilet didn't have recognizable type! "
|
|
||||||
"(Level ${feature.level}, Name ${feature.name}, "
|
|
||||||
"Location: ${feature.getPoint().unwrap()})");
|
|
||||||
icon = Icons.wc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
final point = feature.getPoint().unwrap();
|
|
||||||
return Marker(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
point: point,
|
|
||||||
builder: (ctx) => Icon(
|
|
||||||
icon,
|
|
||||||
color: Colors.purple,
|
|
||||||
),
|
|
||||||
rotateAlignment: Alignment.center,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
LevelLayer(
|
|
||||||
filter: (feature) =>
|
|
||||||
feature.type is Stairs &&
|
|
||||||
(feature.type as Stairs).connects_levels.contains(level),
|
|
||||||
markerConstructor: (feature) {
|
|
||||||
final point = feature.getPoint().unwrap();
|
|
||||||
return Marker(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
point: point,
|
|
||||||
builder: (ctx) => Icon(
|
|
||||||
Icons.stairs_outlined,
|
|
||||||
color: Colors.deepPurple.shade300,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
LevelLayer(
|
|
||||||
filter: (feature) =>
|
|
||||||
feature.type is Lift &&
|
|
||||||
(feature.type as Lift).connects_levels.contains(level),
|
|
||||||
markerConstructor: (feature) {
|
|
||||||
final point = feature.getPoint().unwrap();
|
|
||||||
return Marker(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
point: point,
|
|
||||||
builder: (ctx) => const Icon(
|
|
||||||
Icons.elevator_outlined,
|
|
||||||
color: Colors.deepPurple,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
class LevelLayer extends StatelessWidget {
|
|
||||||
final bool Function(Feature)? filter;
|
|
||||||
final Polygon Function(Feature)? polyConstructor;
|
|
||||||
final Marker Function(LatLng, String)? polyCenterMarkerConstructor;
|
|
||||||
final Marker Function(Feature)? markerConstructor;
|
|
||||||
final int? level;
|
|
||||||
|
|
||||||
const LevelLayer({
|
|
||||||
this.level,
|
|
||||||
this.filter,
|
|
||||||
this.polyConstructor,
|
|
||||||
this.polyCenterMarkerConstructor,
|
|
||||||
this.markerConstructor,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final myMapController = Get.find<MyMapController>();
|
|
||||||
|
|
||||||
return Obx(() {
|
|
||||||
final List<Polygon> filteredPolygons = [];
|
|
||||||
final List<Marker> polygonCenterMarkers = [];
|
|
||||||
final List<Marker> filteredMarkers = [];
|
|
||||||
|
|
||||||
for (final feature in myMapController.features) {
|
|
||||||
if (filter == null || filter!(feature)) {
|
|
||||||
if (feature.isPolygon()) {
|
|
||||||
if (polyConstructor != null) {
|
|
||||||
filteredPolygons.add(polyConstructor!(feature));
|
|
||||||
} else {
|
|
||||||
filteredPolygons.add(feature.getPolygon().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate polygon center
|
|
||||||
final center =
|
|
||||||
polygonCenterMinmax(feature.getPolygon().unwrap().points);
|
|
||||||
if (polyCenterMarkerConstructor != null) {
|
|
||||||
polygonCenterMarkers
|
|
||||||
.add(polyCenterMarkerConstructor!(center, feature.name));
|
|
||||||
} else {
|
|
||||||
polygonCenterMarkers.add(Marker(
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
point: center,
|
|
||||||
builder: (cx) => Center(
|
|
||||||
child: Text(
|
|
||||||
feature.name,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.black54,
|
|
||||||
// backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else if (feature.isPoint()) {
|
|
||||||
if (markerConstructor != null) {
|
|
||||||
filteredMarkers.add(markerConstructor!(feature));
|
|
||||||
} else {
|
|
||||||
final point = feature.getPoint().unwrap();
|
|
||||||
filteredMarkers.add(Marker(
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
point: point,
|
|
||||||
builder: (cx) => Center(
|
|
||||||
child: Text(
|
|
||||||
feature.name,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.black54,
|
|
||||||
// backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// print(filteredPolygons.length);
|
|
||||||
// print(filteredPolygons);
|
|
||||||
|
|
||||||
// print(filteredPolygons[0].points[0]);
|
|
||||||
// print(myMapController.features.length);
|
|
||||||
|
|
||||||
final List<Widget> widgets = [];
|
|
||||||
if (filteredPolygons.isNotEmpty) {
|
|
||||||
if (polyConstructor != null) {
|
|
||||||
widgets.add(PolygonLayer(polygons: filteredPolygons));
|
|
||||||
} else {
|
|
||||||
widgets.add(PolygonLayer(
|
|
||||||
polygons: filteredPolygons
|
|
||||||
.map((poly) => Polygon(
|
|
||||||
points: poly.points,
|
|
||||||
borderColor: Colors.black26,
|
|
||||||
borderStrokeWidth: 2.0,
|
|
||||||
))
|
|
||||||
.toList()));
|
|
||||||
}
|
|
||||||
widgets.add(MarkerLayer(
|
|
||||||
markers: polygonCenterMarkers,
|
|
||||||
rotate: true,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filteredMarkers.isNotEmpty) {
|
|
||||||
widgets.add(MarkerLayer(markers: filteredMarkers, rotate: true));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stack(children: widgets);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
92
pubspec.lock
92
pubspec.lock
@ -185,6 +185,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
version: "1.0.8"
|
||||||
|
dart_earcut:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dart_earcut
|
||||||
|
sha256: "41b493147e30a051efb2da1e3acb7f38fe0db60afba24ac1ea5684cee272721e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -193,14 +201,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.6"
|
version: "2.3.6"
|
||||||
extra_pedantic:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: extra_pedantic
|
|
||||||
sha256: eb9cc0842dc1c980f00fd226364456d2169d54f7118b8ae16443188063edce0b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.5.0"
|
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -242,10 +242,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_map
|
name: flutter_map
|
||||||
sha256: "52c65a977daae42f9aae6748418dd1535eaf27186e9bac9bf431843082bc75a3"
|
sha256: bee8c5bacb49a68aabcf6009c050a8b3b07ac75403f29f741d8c00d4a725e086
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "7.0.0-dev.1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -280,30 +280,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
geodesy:
|
geojson_vi:
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: geodesy
|
|
||||||
sha256: d9959000de938adf760f946546ccbf9ebdff8f4f6d0b5c54e8b8b1ed350b1028
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.4.0-nullsafety.0"
|
|
||||||
geojson:
|
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: geojson
|
name: geojson_vi
|
||||||
sha256: "8aab8116d074e92ef2d1ade25ec5ae90ea8bf024a920ab46703c433ffe08878f"
|
sha256: ffba1991df4d3f98cfd7fee02bcde00b76a39d4daa838ba8a0ba8b83cbff0705
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "2.2.3"
|
||||||
geopoint:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: geopoint
|
|
||||||
sha256: "594afb50a689e6584b80b7de8332c83a78e50725dc4324b2c014d19c56de5e3f"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
get:
|
get:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -332,10 +316,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
|
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.6"
|
version: "1.2.1"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -368,14 +352,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
iso:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: iso
|
|
||||||
sha256: "7030a1a096f7924deb6cccde6c7d80473dddd54eeedf20402e3d6e51b1672b27"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -404,10 +380,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: latlong2
|
name: latlong2
|
||||||
sha256: "08ef7282ba9f76e8495e49e2dc4d653015ac929dce5f92b375a415d30b407ea0"
|
sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.2"
|
version: "0.9.1"
|
||||||
leak_tracker:
|
leak_tracker:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -448,6 +424,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
logger:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logger
|
||||||
|
sha256: "8c94b8c219e7e50194efc8771cd0e9f10807d8d3e219af473d89b06cc2ee4e04"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -512,14 +496,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
pedantic:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pedantic
|
|
||||||
sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.11.1"
|
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -597,14 +573,6 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.99"
|
version: "0.0.99"
|
||||||
slugify:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: slugify
|
|
||||||
sha256: b272501565cb28050cac2d96b7bf28a2d24c8dae359280361d124f3093d337c3
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
source_gen:
|
source_gen:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -701,14 +669,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
tuple:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: tuple
|
|
||||||
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -38,9 +38,12 @@ dependencies:
|
|||||||
get: ^4.6.6
|
get: ^4.6.6
|
||||||
yaml: ^3.1.2
|
yaml: ^3.1.2
|
||||||
surrealdb: ^0.8.0
|
surrealdb: ^0.8.0
|
||||||
geojson: ^1.0.0
|
# geojson: ^1.0.0
|
||||||
flutter_map: 7.0.0-dev.1
|
flutter_map: 7.0.0-dev.1
|
||||||
# latlong2: ^0.9.0
|
# flutter_map: ^4.0.0
|
||||||
|
latlong2: ^0.9.0
|
||||||
|
# latlong2: ^0.8.0
|
||||||
|
geojson_vi: ^2.2.3
|
||||||
url_launcher: ^6.2.6
|
url_launcher: ^6.2.6
|
||||||
anim_search_bar: ^2.0.3
|
anim_search_bar: ^2.0.3
|
||||||
freezed_annotation: ^2.4.1
|
freezed_annotation: ^2.4.1
|
||||||
|
Loading…
Reference in New Issue
Block a user