I wish to place markers using .svg images as icons. I am using google_maps_flutter library. This worked with .png converted images but I didn't find a way to use .svg files directly.
I am posting here after reading this issue : Using SVG markers in google_maps_flutter Flutter plugin
And trying to use the method fromAssetImage as described in this thread : How to change the icon size of Google Map marker in Flutter?
I hoped that this new version of the library would help solve my issue.
I tried solving it with the following code :
MapWidget class
for (Place place in widget.places) {
place.toMarker(
context,
() => _onPlaceTapped(place),
).then(setState((){
markerSet.add
}));
}
Place class
Future<Marker> toMarker(BuildContext context, VoidCallback onTap) async {
return Marker(
markerId: MarkerId(id.toString()),
position: LatLng(lat, lon),
icon: await category.markerIcon(createLocalImageConfiguration(context)),
onTap: onTap,
);
Category class
Future<BitmapDescriptor> markerIcon(ImageConfiguration configuration) async {
BitmapDescriptor b;
switch (type) {
case CategoryType.FirstCategory:
b = await BitmapDescriptor.fromAssetImage(configuration, 'assets/markers/marker-first.svg');
break;
case CategoryType.SecondCategory:
b = await BitmapDescriptor.fromAssetImage(configuration, 'assets/markers/marker-second.svg');
break;
default:
b = await BitmapDescriptor.fromAssetImage(configuration, 'assets/markers/marker-third.svg');
break;
}
return b;
}
The images' path is already added to pubspec.yaml if you are wondering.
I expected the default red google markers to be replaced by some custom markers (there should be a small icon image on each custom marker) on the map, however only default markers are shown (not the default in the switch statement, I am speaking of google's default markers).
There is no error message using iOS simulator and google_maps_flutter 0.5.15+1 library version.
You can find the answer to this question here :
Using SVG markers in google_maps_flutter Flutter plugin
I tried rednuht's answer and it worked like a charm.
EDIT (recap)
The answer requires the use of flutter_svg plugin (^0.13 or 0.14.1 seemed to work for myself).
First, create a function that will give you a BitmapDescriptor from the asset. Make sure the asset is declared in your pubspec file.
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
Future<BitmapDescriptor> _bitmapDescriptorFromSvgAsset(BuildContext context, String assetName) async {
String svgString = await DefaultAssetBundle.of(context).loadString(assetName);
//Draws string representation of svg to DrawableRoot
DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, null);
ui.Picture picture = svgDrawableRoot.toPicture();
ui.Image image = await picture.toImage(26, 37);
ByteData bytes = await image.toByteData(format: ui.ImageByteFormat.png);
return BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
}
I instantiated a Map object at the start of my app so that I could use the BitmapDescriptors without using a lot of async/await calls.
data_model.dart
Map<CategoryType, BitmapDescriptor> descriptors = Map<Category, BitmapDescriptor>();
Future<void> loadBitmapDescriptors(context) async {
descriptors[CategoryType.FirstCatgory] = await _bitmapDescriptorFromSvgAsset(context, 'assets/markers/marker-first.svg');
descriptors[CategoryType.SecondCategory] = await _bitmapDescriptorFromSvgAsset(context, 'assets/markers/marker-second.svg');
descriptors[CategoryType.ThirdCategory] = await _bitmapDescriptorFromSvgAsset(context, 'assets/markers/marker-third.svg');
}
main.dart
DataModel.of(context).loadBitmapDescriptors(context);
So all I had to do after that was to call it correctly when needed.
Marker marker = Marker(markerId: MarkerId(id.toString()), icon: descriptors[category], position: LatLng(lat, lon));
I had the same problem and ended with this implementation due to without de devicePixelRatio It was showing pixelated markers.
Future<BitmapDescriptor> getBitmapDescriptorFromSVGAsset(
BuildContext context,
String svgAssetLink, {
Size size = const Size(30, 30),
}) async {
String svgString = await DefaultAssetBundle.of(context).loadString(
svgAssetLink,
);
final drawableRoot = await svg.fromSvgString(
svgString,
'debug: $svgAssetLink',
);
final ratio = ui.window.devicePixelRatio.ceil();
final width = size.width.ceil() * ratio;
final height = size.height.ceil() * ratio;
final picture = drawableRoot.toPicture(
size: Size(
width.toDouble(),
height.toDouble(),
),
);
final image = await picture.toImage(width, height);
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final uInt8List = byteData.buffer.asUint8List();
return BitmapDescriptor.fromBytes(uInt8List);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With