Skip to content

Commit 4c0bd6f

Browse files
feat: added Poly*Layer.drawInSingleWorld (#2069)
Co-authored-by: Luka S <[email protected]>
1 parent 392b049 commit 4c0bd6f

File tree

13 files changed

+537
-162
lines changed

13 files changed

+537
-162
lines changed

example/lib/main.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@ import 'package:flutter_map_example/pages/many_markers.dart';
1515
import 'package:flutter_map_example/pages/map_controller.dart';
1616
import 'package:flutter_map_example/pages/map_inside_listview.dart';
1717
import 'package:flutter_map_example/pages/markers.dart';
18-
import 'package:flutter_map_example/pages/multi_worlds.dart';
1918
import 'package:flutter_map_example/pages/overlay_image.dart';
2019
import 'package:flutter_map_example/pages/plugin_zoombuttons.dart';
2120
import 'package:flutter_map_example/pages/polygon.dart';
2221
import 'package:flutter_map_example/pages/polygon_perf_stress.dart';
2322
import 'package:flutter_map_example/pages/polyline.dart';
2423
import 'package:flutter_map_example/pages/polyline_perf_stress.dart';
24+
import 'package:flutter_map_example/pages/repeated_worlds.dart';
2525
import 'package:flutter_map_example/pages/reset_tile_layer.dart';
2626
import 'package:flutter_map_example/pages/retina.dart';
2727
import 'package:flutter_map_example/pages/scalebar.dart';
2828
import 'package:flutter_map_example/pages/screen_point_to_latlng.dart';
2929
import 'package:flutter_map_example/pages/secondary_tap.dart';
30+
import 'package:flutter_map_example/pages/single_world_polys.dart';
3031
import 'package:flutter_map_example/pages/sliding_map.dart';
3132
import 'package:flutter_map_example/pages/tile_builder.dart';
3233
import 'package:flutter_map_example/pages/tile_loading_error_handle.dart';
@@ -54,6 +55,7 @@ class MyApp extends StatelessWidget {
5455
CancellableTileProviderPage.route: (context) =>
5556
const CancellableTileProviderPage(),
5657
PolylinePage.route: (context) => const PolylinePage(),
58+
SingleWorldPolysPage.route: (context) => const SingleWorldPolysPage(),
5759
PolylinePerfStressPage.route: (context) =>
5860
const PolylinePerfStressPage(),
5961
MapControllerPage.route: (context) => const MapControllerPage(),
@@ -67,7 +69,7 @@ class MyApp extends StatelessWidget {
6769
CirclePage.route: (context) => const CirclePage(),
6870
OverlayImagePage.route: (context) => const OverlayImagePage(),
6971
PolygonPage.route: (context) => const PolygonPage(),
70-
MultiWorldsPage.route: (context) => const MultiWorldsPage(),
72+
RepeatedWorldsPage.route: (context) => const RepeatedWorldsPage(),
7173
PolygonPerfStressPage.route: (context) => const PolygonPerfStressPage(),
7274
SlidingMapPage.route: (_) => const SlidingMapPage(),
7375
WMSLayerPage.route: (context) => const WMSLayerPage(),
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ import 'package:flutter_map_example/widgets/drawer/menu_drawer.dart';
55
import 'package:latlong2/latlong.dart';
66

77
/// Example dedicated to replicated worlds and related objects (e.g. Markers).
8-
class MultiWorldsPage extends StatefulWidget {
9-
static const String route = '/multi_worlds';
8+
class RepeatedWorldsPage extends StatefulWidget {
9+
static const String route = '/repeated_worlds';
1010

11-
const MultiWorldsPage({super.key});
11+
const RepeatedWorldsPage({super.key});
1212

1313
@override
14-
State<MultiWorldsPage> createState() => _MultiWorldsPageState();
14+
State<RepeatedWorldsPage> createState() => _RepeatedWorldsPageState();
1515
}
1616

17-
class _MultiWorldsPageState extends State<MultiWorldsPage> {
17+
class _RepeatedWorldsPageState extends State<RepeatedWorldsPage> {
1818
final LayerHitNotifier<String> _hitNotifier = ValueNotifier(null);
1919

2020
final _customMarkers = <Marker>[];
@@ -38,15 +38,16 @@ class _MultiWorldsPageState extends State<MultiWorldsPage> {
3838
@override
3939
Widget build(BuildContext context) {
4040
return Scaffold(
41-
appBar: AppBar(title: const Text('Multi-worlds')),
42-
drawer: const MenuDrawer(MultiWorldsPage.route),
41+
appBar: AppBar(
42+
title: const Text('Repeated Worlds/Longitudes'),
43+
),
44+
drawer: const MenuDrawer(RepeatedWorldsPage.route),
4345
body: Stack(
4446
children: [
4547
FlutterMap(
4648
options: MapOptions(
47-
initialCenter: const LatLng(51.5, -0.09),
48-
initialZoom: 0,
49-
initialRotation: 0,
49+
initialCenter: const LatLng(0, 0),
50+
initialZoom: 2,
5051
onTap: (_, p) => setState(() => _customMarkers.add(_buildPin(p))),
5152
),
5253
children: [
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_map/flutter_map.dart';
3+
import 'package:flutter_map_example/misc/tile_providers.dart';
4+
import 'package:flutter_map_example/widgets/drawer/menu_drawer.dart';
5+
import 'package:latlong2/latlong.dart';
6+
7+
@immutable
8+
class Epsg3857NoRepeat extends Epsg3857 {
9+
const Epsg3857NoRepeat();
10+
11+
@override
12+
bool get replicatesWorldLongitude => false;
13+
}
14+
15+
/// Demo of how the new `drawInSingleWorld` parameter works on Poly*Layer's.
16+
///
17+
/// cf. https://github.com/fleaflet/flutter_map/issues/2067
18+
class SingleWorldPolysPage extends StatefulWidget {
19+
static const String route = '/single_world_polys';
20+
21+
const SingleWorldPolysPage({super.key});
22+
23+
@override
24+
State<SingleWorldPolysPage> createState() => _SingleWorldPolysPageState();
25+
}
26+
27+
class _SingleWorldPolysPageState extends State<SingleWorldPolysPage> {
28+
bool _repeatLongitudes = false;
29+
30+
static const _polylinePoints = [
31+
LatLng(40, 150),
32+
LatLng(45, 160),
33+
LatLng(50, 170),
34+
LatLng(55, 180),
35+
LatLng(50, -170),
36+
LatLng(45, -160),
37+
LatLng(40, -150),
38+
];
39+
40+
static const _polygonPoints = [
41+
LatLng(40, 150),
42+
LatLng(45, 160),
43+
LatLng(50, 170),
44+
LatLng(55, 180),
45+
LatLng(50, -170),
46+
LatLng(45, -160),
47+
LatLng(40, -150),
48+
LatLng(35, -160),
49+
LatLng(30, -170),
50+
LatLng(25, -180),
51+
LatLng(30, 170),
52+
LatLng(35, 160),
53+
];
54+
55+
static const _polygonHolePoints = [
56+
LatLng(45, 175),
57+
LatLng(45, -175),
58+
LatLng(35, -175),
59+
LatLng(35, 175),
60+
];
61+
62+
@override
63+
Widget build(BuildContext context) {
64+
return Scaffold(
65+
appBar: AppBar(title: const Text('Single World Polys')),
66+
drawer: const MenuDrawer(SingleWorldPolysPage.route),
67+
body: Stack(
68+
children: [
69+
FlutterMap(
70+
options: MapOptions(
71+
initialCenter: const LatLng(0, 0),
72+
initialZoom: 0,
73+
crs: _repeatLongitudes
74+
? const Epsg3857()
75+
: const Epsg3857NoRepeat(),
76+
),
77+
children: [
78+
openStreetMapTileLayer,
79+
PolygonLayer(
80+
simplificationTolerance: 0,
81+
drawInSingleWorld: false,
82+
polygons: [
83+
Polygon(
84+
points: _polygonPoints
85+
.map((latLng) =>
86+
LatLng(latLng.latitude - 20, latLng.longitude))
87+
.toList(),
88+
holePointsList: [
89+
_polygonHolePoints
90+
.map((latLng) =>
91+
LatLng(latLng.latitude - 20, latLng.longitude))
92+
.toList(),
93+
],
94+
color: const Color(0xFF0000FF),
95+
borderColor: Colors.purple,
96+
borderStrokeWidth: 6,
97+
pattern: const StrokePattern.dotted(),
98+
),
99+
Polygon(
100+
points: _polygonPoints
101+
.map((latLng) =>
102+
LatLng(latLng.latitude - 80, latLng.longitude))
103+
.toList(),
104+
color: const Color(0xFF000000),
105+
),
106+
],
107+
),
108+
PolygonLayer(
109+
simplificationTolerance: 0,
110+
drawInSingleWorld: true,
111+
polygons: [
112+
Polygon(
113+
points: _polygonPoints
114+
.map((latLng) =>
115+
LatLng(latLng.latitude - 55, latLng.longitude))
116+
.toList(),
117+
holePointsList: [
118+
_polygonHolePoints
119+
.map((latLng) =>
120+
LatLng(latLng.latitude - 55, latLng.longitude))
121+
.toList(),
122+
],
123+
color: const Color(0xFF0000FF),
124+
borderColor: Colors.purple,
125+
borderStrokeWidth: 6,
126+
pattern: const StrokePattern.dotted(),
127+
),
128+
Polygon(
129+
points: _polygonPoints
130+
.map((latLng) =>
131+
LatLng(latLng.latitude - 110, latLng.longitude))
132+
.toList(),
133+
color: const Color(0xFF000000),
134+
),
135+
],
136+
),
137+
PolylineLayer(
138+
simplificationTolerance: 0,
139+
drawInSingleWorld: false,
140+
polylines: [
141+
Polyline(
142+
points: _polylinePoints
143+
.map((latLng) =>
144+
LatLng(latLng.latitude + 25, latLng.longitude))
145+
.toList(),
146+
strokeWidth: 8,
147+
color: const Color(0xFFFF0000),
148+
pattern: const StrokePattern.dotted(),
149+
),
150+
Polyline(
151+
points: const [
152+
LatLng(-80, 150),
153+
LatLng(-80, -170),
154+
LatLng(-75, -170),
155+
LatLng(-75, 150),
156+
LatLng(-80, 150),
157+
],
158+
strokeWidth: 8,
159+
color: Colors.yellow,
160+
),
161+
],
162+
),
163+
PolylineLayer(
164+
simplificationTolerance: 0,
165+
drawInSingleWorld: true,
166+
polylines: [
167+
Polyline(
168+
points: _polylinePoints
169+
.map((latLng) =>
170+
LatLng(latLng.latitude + 0, latLng.longitude))
171+
.toList(),
172+
strokeWidth: 8,
173+
color: Colors.red,
174+
pattern: StrokePattern.dashed(segments: [50, 20]),
175+
),
176+
Polyline(
177+
points: const [
178+
LatLng(80, 150),
179+
LatLng(80, -170),
180+
LatLng(75, -170),
181+
LatLng(75, 150),
182+
LatLng(80, 150),
183+
],
184+
strokeWidth: 8,
185+
color: Colors.yellow,
186+
),
187+
],
188+
), /*PolygonLayer(
189+
drawInSingleWorld: true,
190+
polygons: [
191+
Polygon(
192+
points: [
193+
const LatLng(90, -180),
194+
const LatLng(90, 180),
195+
const LatLng(-90, 180),
196+
const LatLng(-90, -180),
197+
],
198+
color: Colors.amber,
199+
borderColor: Colors.black,
200+
borderStrokeWidth: 5,
201+
holePointsList: [
202+
[
203+
LatLng(46, -9),
204+
LatLng(46, -8),
205+
LatLng(45.5, -7.5),
206+
LatLng(45, -8),
207+
LatLng(45, -9),
208+
]
209+
],
210+
),
211+
],
212+
),*/
213+
],
214+
),
215+
Align(
216+
alignment: Alignment.topRight,
217+
child: Container(
218+
decoration: BoxDecoration(
219+
color: Theme.of(context).colorScheme.surface,
220+
borderRadius: BorderRadius.circular(32),
221+
),
222+
padding: const EdgeInsets.symmetric(
223+
vertical: 8,
224+
horizontal: 16,
225+
),
226+
margin: const EdgeInsets.all(16),
227+
child: Row(
228+
mainAxisSize: MainAxisSize.min,
229+
spacing: 16,
230+
children: [
231+
const Tooltip(
232+
message: 'Prevent unbounded horizontal scrolling',
233+
child: Icon(
234+
Icons.screen_lock_landscape,
235+
size: 32,
236+
),
237+
),
238+
Switch.adaptive(
239+
value: !_repeatLongitudes,
240+
onChanged: (v) => setState(() => _repeatLongitudes = !v),
241+
),
242+
],
243+
),
244+
),
245+
),
246+
],
247+
),
248+
);
249+
}
250+
}

example/lib/widgets/drawer/menu_drawer.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,19 @@ import 'package:flutter_map_example/pages/many_markers.dart';
1616
import 'package:flutter_map_example/pages/map_controller.dart';
1717
import 'package:flutter_map_example/pages/map_inside_listview.dart';
1818
import 'package:flutter_map_example/pages/markers.dart';
19-
import 'package:flutter_map_example/pages/multi_worlds.dart';
2019
import 'package:flutter_map_example/pages/overlay_image.dart';
2120
import 'package:flutter_map_example/pages/plugin_zoombuttons.dart';
2221
import 'package:flutter_map_example/pages/polygon.dart';
2322
import 'package:flutter_map_example/pages/polygon_perf_stress.dart';
2423
import 'package:flutter_map_example/pages/polyline.dart';
2524
import 'package:flutter_map_example/pages/polyline_perf_stress.dart';
25+
import 'package:flutter_map_example/pages/repeated_worlds.dart';
2626
import 'package:flutter_map_example/pages/reset_tile_layer.dart';
2727
import 'package:flutter_map_example/pages/retina.dart';
2828
import 'package:flutter_map_example/pages/scalebar.dart';
2929
import 'package:flutter_map_example/pages/screen_point_to_latlng.dart';
3030
import 'package:flutter_map_example/pages/secondary_tap.dart';
31+
import 'package:flutter_map_example/pages/single_world_polys.dart';
3132
import 'package:flutter_map_example/pages/sliding_map.dart';
3233
import 'package:flutter_map_example/pages/tile_builder.dart';
3334
import 'package:flutter_map_example/pages/tile_loading_error_handle.dart';
@@ -110,9 +111,15 @@ class MenuDrawer extends StatelessWidget {
110111
routeName: ScaleBarPage.route,
111112
currentRoute: currentRoute,
112113
),
114+
const Divider(),
115+
MenuItemWidget(
116+
caption: 'Repeated Worlds/Longitudes',
117+
routeName: RepeatedWorldsPage.route,
118+
currentRoute: currentRoute,
119+
),
113120
MenuItemWidget(
114-
caption: 'Multi-world and layers',
115-
routeName: MultiWorldsPage.route,
121+
caption: 'Single World Polys',
122+
routeName: SingleWorldPolysPage.route,
116123
currentRoute: currentRoute,
117124
),
118125
const Divider(),

0 commit comments

Comments
 (0)