MapView Markers

这篇文档目前尚未提供译文,将以原文展示。

Introduction

This example shows how to add markers in bulk

  1. Add markers in bulk to MapView
  2. Long Click MapView to Add a marker with clicked point
Android snapshot iOS snapshot

For all code examples, refer to Flutter Maps SDK Code Examples

CustomMarkerPage view source

1import 'dart:io';
2import 'dart:math';
3
4import 'package:flutter/foundation.dart';
5import 'package:flutter/material.dart';
6import 'package:flutter/widgets.dart'; // ignore: unnecessary_import
7import 'package:nb_maps_flutter/nb_maps_flutter.dart';
8
9import 'page.dart';
10
11const randomMarkerNum = 10;
12
13class CustomMarkerPage extends ExamplePage {
14 CustomMarkerPage() : super(const Icon(Icons.place), 'Custom marker');
15
16 
17 Widget build(BuildContext context) {
18   return CustomMarker();
19 }
20}
21
22class CustomMarker extends StatefulWidget {
23 const CustomMarker();
24
25 
26 State createState() => CustomMarkerState();
27}
28
29class CustomMarkerState extends State<CustomMarker> {
30 final Random _rnd = new Random();
31
32 late NextbillionMapController _mapController;
33 List<Marker> _markers = [];
34 List<_MarkerState> _markerStates = [];
35
36 void _addMarkerStates(_MarkerState markerState) {
37   _markerStates.add(markerState);
38 }
39
40 void _onMapCreated(NextbillionMapController controller) {
41   _mapController = controller;
42   controller.addListener(() {
43     if (controller.isCameraMoving) {
44       _updateMarkerPosition();
45     }
46   });
47 }
48
49 void _onStyleLoadedCallback() {
50   print('onStyleLoadedCallback');
51 }
52
53 void _onMapLongClickCallback(Point<double> point, LatLng coordinates) {
54   _addMarker(point, coordinates);
55 }
56
57 void _onCameraIdleCallback() {
58   _updateMarkerPosition();
59 }
60
61 void _updateMarkerPosition() {
62   final coordinates = <LatLng>[];
63
64   for (final markerState in _markerStates) {
65     coordinates.add(markerState.getCoordinate());
66   }
67
68   _mapController.toScreenLocationBatch(coordinates).then((points) {
69     _markerStates.asMap().forEach((i, value) {
70       _markerStates[i].updatePosition(points[i]);
71     });
72   });
73 }
74
75 void _addMarker(Point<double> point, LatLng coordinates) {
76   setState(() {
77     _markers.add(Marker(_rnd.nextInt(100000).toString(), coordinates, point,
78         _addMarkerStates));
79   });
80 }
81
82 
83 Widget build(BuildContext context) {
84   return new Container(
85     child: Stack(children: [
86       NBMap(
87         trackCameraPosition: true,
88         onMapCreated: _onMapCreated,
89         onMapLongClick: _onMapLongClickCallback,
90         onCameraIdle: _onCameraIdleCallback,
91         onStyleLoadedCallback: _onStyleLoadedCallback,
92         initialCameraPosition:
93             const CameraPosition(target: LatLng(35.0, 135.0), zoom: 5),
94       ),
95       IgnorePointer(
96           ignoring: true,
97           child: Stack(
98             children: _markers,
99           )),
100       FloatingActionButton(
101         onPressed: () {
102           // Generate random markers
103           var param = <LatLng>[];
104           for (var i = 0; i < randomMarkerNum; i++) {
105             final lat = _rnd.nextDouble() * 20 + 30;
106             final lng = _rnd.nextDouble() * 20 + 125;
107             param.add(LatLng(lat, lng));
108           }
109
110           _mapController.toScreenLocationBatch(param).then((value) {
111             for (var i = 0; i < randomMarkerNum; i++) {
112               var point =
113                   Point<double>(value[i].x as double, value[i].y as double);
114               _addMarker(point, param[i]);
115             }
116           });
117         },
118         child: Icon(Icons.add),
119       ),
120     ]),
121   );
122 }
123
124 // ignore: unused_element
125 void _measurePerformance() {
126   final trial = 10;
127   final batches = [500, 1000, 1500, 2000, 2500, 3000];
128   var results = Map<int, List<double>>();
129   for (final batch in batches) {
130     results[batch] = [0.0, 0.0];
131   }
132
133   _mapController.toScreenLocation(LatLng(0, 0));
134   Stopwatch sw = Stopwatch();
135
136   for (final batch in batches) {
137     //
138     // primitive
139     //
140     for (var i = 0; i < trial; i++) {
141       sw.start();
142       var list = <Future<Point<num>>>[];
143       for (var j = 0; j < batch; j++) {
144         var p = _mapController
145             .toScreenLocation(LatLng(j.toDouble() % 80, j.toDouble() % 300));
146         list.add(p);
147       }
148       Future.wait(list);
149       sw.stop();
150       results[batch]![0] += sw.elapsedMilliseconds;
151       sw.reset();
152     }
153
154     //
155     // batch
156     //
157     for (var i = 0; i < trial; i++) {
158       sw.start();
159       var param = <LatLng>[];
160       for (var j = 0; j < batch; j++) {
161         param.add(LatLng(j.toDouble() % 80, j.toDouble() % 300));
162       }
163       Future.wait([_mapController.toScreenLocationBatch(param)]);
164       sw.stop();
165       results[batch]![1] += sw.elapsedMilliseconds;
166       sw.reset();
167     }
168
169     print(
170         'batch=$batch,primitive=${results[batch]![0] / trial}ms, batch=${results[batch]![1] / trial}ms');
171   }
172 }
173}
174
175class Marker extends StatefulWidget {
176 final Point _initialPosition;
177 final LatLng _coordinate;
178 final void Function(_MarkerState) _addMarkerState;
179
180 Marker(
181     String key, this._coordinate, this._initialPosition, this._addMarkerState)
182     : super(key: Key(key));
183
184 
185 State<StatefulWidget> createState() {
186   final state = _MarkerState(_initialPosition);
187   _addMarkerState(state);
188   return state;
189 }
190}
191
192class _MarkerState extends State with TickerProviderStateMixin {
193 final _iconSize = 20.0;
194
195 Point _position;
196
197 _MarkerState(this._position);
198
199 
200 void initState() {
201   super.initState();
202 }
203
204 
205 void dispose() {
206   super.dispose();
207 }
208
209 
210 Widget build(BuildContext context) {
211   var ratio = 1.0;
212
213   // web does not support Platform._operatingSystem
214   if (!kIsWeb) {
215     // iOS returns logical pixel while Android returns screen pixel
216     ratio = Platform.isIOS ? 1.0 : MediaQuery.of(context).devicePixelRatio;
217   }
218
219   return Positioned(
220       left: _position.x / ratio - _iconSize / 2,
221       top: _position.y / ratio - _iconSize / 2,
222       child: Image.asset('assets/symbols/2.0x/custom-icon.png',
223           height: _iconSize));
224 }
225
226 void updatePosition(Point<num> point) {
227   setState(() {
228     _position = point;
229   });
230 }
231
232 LatLng getCoordinate() {
233   return (widget as Marker)._coordinate;
234 }
235}

Code summary

The above code snippet demonstrates how to implement a custom marker feature in a Flutter application using the nb_maps_flutter package. The custom markers are added to the map when:

  1. the user performs a long-press gesture
  2. User click on the floating button on the top left corner And the marker positions are updated when the map is moved.

CustomMarker Class: is a StatefulWidget class that represents the custom marker widget. It uses the NextbillionMapController to interact with the map and manages a list of custom _MarkerState instances to keep track of the markers on the map.

CustomMarkerState Class: is the state class for the CustomMarker widget. It handles map-related events and manages the markers on the map. Notable methods include:

  1. _onMapCreated: Handles the initialization of the map controller and sets up a listener for camera movements.
  2. _onStyleLoadedCallback: A callback method that is called when the map style is loaded.
  3. _onMapLongClickCallback: Handles the event when the user long-presses on the map to add a new custom marker.
  4. _onCameraIdleCallback: Handles the event when the camera stops moving and triggers the update of marker positions.
  5. _addMarker: Adds a new custom marker to the map and updates the list of markers.

build Method: returns a Container widget containing a Stack with multiple child widgets:

  1. NBMap: The actual map widget, provided by the nb_maps_flutter package. It handles user interactions and displays the custom markers on the map.
  2. IgnorePointer: A widget that ignores touch events, ensuring that the custom markers do not interfere with user interactions with the map.
  3. FloatingActionButton: A button that, when pressed, generates and adds random markers to the map.

_MarkerState Class: This class represents the state of a custom marker. It extends State and is responsible for rendering the custom marker image on the map. Notable methods include:

  1. build: Builds the marker widget based on the marker's position and icon image.
  2. updatePosition: Updates the marker's position when the map is moved.
  3. getCoordinate: Retrieves the coordinate of the marker on the map.
没找到你要找的内容?