I found this library: https://pub.dev/packages/flutter_map_picker
I looked through his code and tried figuring out how he initiates drawing. What he accomplishes is far more complicated than I need, and I can't figure out the first step of what he did. I also don't want to take the guy's code. Can anyone explain how to accomplish this?
I just want to be able to circle objects on my map. There seems to be a polyline solution but it's just straight lines from a list of coordinates, not exactly what I'm looking for.
A Stack widget with GoogleMap and CustomPaint will let you draw anything you want on top of the map.
Stack(
children: <Widget>[
_position == null
? Text('Waiting for location . .')
: GoogleMap(
liteModeEnabled: false,
compassEnabled: true,
mapType: MapType.hybrid,
markers: Set<Marker>.of(markers.values),
initialCameraPosition: CameraPosition(
target: LatLng(_position.latitude, _position.longitude),
zoom: 17,
tilt: 0,
),
onMapCreated: (GoogleMapController controller) {
_mapController = controller;
// trigger initial update and paint of landmarks
_updateLandmarks();
},
onCameraMove: (CameraPosition position) {
_updateLandmarks();
},
),
CustomPaint(
foregroundPainter: MapPainter(_landmarksMap),
),
],
)
You have to convert map coordinates to device screen coordinates. Google has a cookbook on how to do that except it does not work in Flutter since the map plugin does not expose the complete API. But there is a way to do it of course.
void _updateLandmarks() async {
double dpi = MediaQuery.of(context).devicePixelRatio;
LatLngBounds bounds = await _mapController.getVisibleRegion();
ScreenCoordinate topRight = await _mapController.getScreenCoordinate(bounds.northeast);
ScreenCoordinate bottomLeft = await _mapController.getScreenCoordinate(bounds.southwest);
_landmarksMap.values.forEach((element) async {
ScreenCoordinate sc = await _mapController.getScreenCoordinate(LatLng(element.pos.latitude, element.pos.longitude));
element.screenPoint.x = ((sc.x - bottomLeft.x) / dpi).floor();
element.screenPoint.y = ((sc.y - topRight.y) / dpi).floor();
});
setState(() {});
}
You can read here for more details: https://aperico.com/google-maps-with-custom-paint-in-flutter/
Related
I am using Stream Builder that sends api request after some seconds and fetch coordinates (lat, lng).
I want to update the map location (camera position & marker) on newly fetch coordinates.
But Camera position is updating and not focusing on new coordinates.
My google map widget is inside of stream builder and in which we are passing data through snapshot
e.g latlng = LatLng(snapshot.data['lat'],snapshot.data['lng']) to markers: SetMarker( markers, markerID, latlng, ), & initialCameraPosition: CameraPosition( target: latlng, zoom: 9.0, )
The GoogleMaps widget on Flutter does have the attribute initialCameraPosition but as the name says this is just an initial value, if you want to update the map once this has loaded i'd recommend the use of the callback onMapCreated, where you can use the controller to animate to a certain position.
Doing so would look something like this:
onMapCreated: (GoogleMapController controller) {
controller.animateCamera(
CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(snapshot.data['lat'],
snapshot.data['lng']),
zoom: 12)));
setState((){});
}
Hope this helps! ;)
I want to make my map moving only when user drag it with two fingers, I still want to have ability to zoom and rotate map. Map is in the Stack widget and also is in the SingleChildScrollView (Stack is under ScrollView and GoogleMap is under Stack).
That's my implementation of map:
GoogleMap(
initialCameraPosition: CameraPosition(
target: _initialPosition,
zoom: ShippingAddressUI.initialZoomValue),
onMapCreated: (GoogleMapController controller) {
_mapController = controller;
},
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
)
I know about gestureRecognizers existing but I have no idea how to use them to do this. I was wondering about MultiDragGestureRecognizer() but gestureRecognizers take only OneSequenceGestureRecognizer() that's why we can't use MultiDragGestureRecognizer() here.
If you have any questions, feel free to ask!
Try this.
GoogleMap(
initialCameraPosition: CameraPosition(
target: .....
),
......
...
gestureRecognizers: Set()
..add(Factory<PanGestureRecognizer>(() => PanGestureRecognizer()))
);
https://pub.dev/packages/flutter_animarker
Wow, this is annoying. So Animarker is a Widget parent for my Google map. The map is busy with Markers. When the user needs to find a particular Marker from the drawer, they tap the item & it triggers a Ripple effect in the corresponding Marker.
The problem is it never stops rippling. It'll even attempt to animate several Markers if the user keeps on tapping.
It was love at first animation but I'm climbing the walls now!
Animarker(
isActiveTrip: rippleAnimationActive,
rippleRadius: 0.5, //[0,1.0] range, how big is the circle
rippleColor: Colors.teal, // Color of fade ripple circle
rippleDuration: Duration(milliseconds: 2500), //Pulse ripple duration
markers: animatedMarkerSet,
mapId: _mapController.future.then<int>((value) => value.mapId),
child: GoogleMap(
key: Key("myGoogleMap"),
mapType: MapType.hybrid,
initialCameraPosition: _edinburghCamera,
markers: _markers,
myLocationEnabled: true,
onMapCreated: (GoogleMapController controller) {
_mapController.complete(controller);
},
),
),
I trigger the animation in a Drawer item onTap():
onTap: () {
animatedMarkerSet = {
RippleMarker(
markerId: MarkerId(presentLocation.name),
position: presentLocation.latLng,
ripple: true) };
setState(() {
presentLocation = _location;
animatedMarkerSet;
rippleAnimationActive = true;
});
//setState(() => _markers.add(marker));
Navigator.of(context).pop();
},
You can see I've created a brand new Marker to animate, and added it to the animatedMarkerSet. This works fine.
When the user taps a Marker, any Marker, details about the location slide up. And I try to deactivate ANY Marker which is rippling. However no matter what I try it doesn't stop:
setState(() {
rippleAnimationActive = false;
animatedMarkerSet.clear(); // nuke from orbit
}
I've also tried changing the animatedMarkerSet to a Map, and attempting to deactivate the ripple using this:
void newLocationUpdate(LocationDetails oldLocation) {
var marker = RippleMarker(
markerId: MarkerId(oldLocation.name),
position: oldLocation.latLng,
ripple: false,
);
setState(() => animatedMarkerMap[MarkerId(oldLocation.name)] = marker);
}
But that doesn't work either.
I really really just need to switch the animation on and off. I don't see why Animarker's so resistant to setState(), telling it to stop.
In fact, the best thing might be to just have it run for 5 seconds then switch off, in all circumstances, but I fail to see how to do that either. Grrrr!
OK well I figured it out. AniMarker which takes the Set of animated Markers, is final. So once you hand it the set of say RippleMarkers, it'll animate them, but you can't then turn it off via a SetState() call.
I tried editing the AniMarker class, to make it not final, so you could mutate it's dataset, but I think because it's built on GoogleMap's Marker class, and they're final, it just will not work.
So AniMarker presently has limited utility.
My work around was just to mutate GoogleMaps marker: option, so I could highlight a Marker by changing it's color. It's also possible to change the circles: GoogleMap option to dyanically highlight a Marker according to user interaction.
I think my issue is the same as here:
Flutter show marker's infoWindowText by default in Google map widget
However, there is no answer, except for a link to another post which isn't quite what I want to do.
When my map opens in my app, it shows the markers correctly, but I also want to have all the labels displaying by default on open...
As the shown by one of the markers here:
I'm creating markers like this:
for (Location location in _locations) {
final locationMarker = Marker(
markerId: MarkerId(location.id),
position: LatLng(location.geoY, location.geoX),
infoWindow: InfoWindow(
title: location.name,
),
onTap: () => _onTap(location),
icon: _mapMarkers.icon(location.slug),
draggable: false);
markers.add(locationMarker);
}
Then the map like this:
Widget _map(Set<Marker> markers) => GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(target: widget.mapCentre),
markers: markers,
...
onMapCreated: (controller) => _onMapCreated(controller, markers),
);
And the in _onMapCreated, I've tried to show all the labels, but only the last in the list of markers is actually displayed:
_onMapCreated(GoogleMapController controller, Set<Marker> markers) {
if (mounted) {
setState(() {
_controller.complete(controller);
controller.setMapStyle(_mapStyle);
for (var marker in markers) {
controller.showMarkerInfoWindow(marker.markerId);
}
});
...
I'm using:
[{
"featureType": "poi",
"stylers": [
{
"visibility": "off"
}
]
}]
to remove points of interest from the maps and I am hoping I can do something similar to get marker labels to display by default, but so far I've not found anything when searching google, or that there's another solution.
You can use showMarkerInfoWindow property the GoogleMapController
final GoogleMapController controller = await _controller.future;
controller.showMarkerInfoWindow(MarkerId('ID_MARKET'));
How to fit polylines to street curves in google maps flutter?
I did being playing with Polylines in google_maps_flutter for 2 months and I have this doubts:
Polylines do not follow the street curves or the highways.
Polylines has the OnTap callback but, on multi-polylines I can not get any ID or attribute to distinguis who I tapped.
can any one give me a hand with this?
I am new in Flutter and I am using the Directions API from Google. Maybe is not the right API to solve this problem.
I need that polyline set follow the street curves.
Polylines in google_maps_flutter
P.S: Sorry if my code bleed your eyes!
google_maps_flutter widget:
GoogleMap(
onMapCreated: (controller) {
_mapController = controller;
},
initialCameraPosition: CameraPosition(
target: getCurrentLocation(),
zoom: 15,
),
mapType: _currentMapType,
myLocationEnabled: true,
myLocationButtonEnabled: false,
compassEnabled: true,
rotateGesturesEnabled: true,
markers: _markers,
polylines: _polyline,
)
Set state to show the polyline and markers:
setState(
() {
_markers.clear();
for (var point in itinerary) {
_markers.add(
Marker(
markerId: MarkerId("stop ${point.latitude}"),
position: LatLng(point.latitude, point.longitude),
infoWindow: InfoWindow(title: point.address),
),
);
}
_polyline.clear();
_polyline.add(
flutter.Polyline(
polylineId: PolylineId("route"),
points: ccc,
width: 8,
color: Colors.red,
geodesic: true,
jointType: JointType.round,
),
);
_mapController.animateCamera(
CameraUpdate.newLatLngZoom(
LatLng(origin.lat, origin.lng), 13.0),
);
},
);
Google Directions API Call:
GoogleMapsDirections(apiKey: apiKey).directions(origin, destination, waypoints: itinerary, ).then((DirectionsResponse response) { return response }
I got some advice from Github member that told me to try SnapToRoad, now I get more details about the route, but the highways are still helicopter's travel
A simple GET to https://roads.googleapis.com/v1/snapToRoads whit the API_KEy and some points of my previus polyline helps.
Here is the link of SnapToRoad
That's because the polyline it's just a line that you draw, to do what you want need to make a route between points and using that generated coordinates make a polyline.
Check this tutorial that i found: https://www.developerlibs.com/2018/08/flutter-how-can-draw-route-on-google.html
try this pub: google_map_polyline