Skip to content

Instantly share code, notes, and snippets.

@kururu-abdo
Created April 7, 2024 23:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kururu-abdo/ea9bda4adbdd0c2d21060890e2ed2b83 to your computer and use it in GitHub Desktop.
Save kururu-abdo/ea9bda4adbdd0c2d21060890e2ed2b83 to your computer and use it in GitHub Desktop.
flutter_map_custom_marker
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
extension ToBitDescription on Widget {
Future<BitmapDescriptor> toBitmapDescriptor({Size? logicalSize, Size? imageSize, Duration waitToRender = const Duration(milliseconds: 300), TextDirection textDirection = TextDirection.ltr}) async {
final widget = RepaintBoundary(
child: MediaQuery(data: const MediaQueryData(), child: Directionality(textDirection: TextDirection.ltr, child: this)),
);
final pngBytes = await createImageFromWidget(widget, waitToRender: waitToRender, logicalSize: logicalSize, imageSize: imageSize);
return BitmapDescriptor.fromBytes(pngBytes);
}
}
/// Creates an image from the given widget by first spinning up a element and render tree,
/// wait [waitToRender] to render the widget that take time like network and asset images
/// The final image will be of size [imageSize] and the the widget will be layout, ... with the given [logicalSize].
/// By default Value of [imageSize] and [logicalSize] will be calculate from the app main window
Future<Uint8List> createImageFromWidget(Widget widget, {Size? logicalSize, required Duration waitToRender, Size? imageSize}) async {
final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();
final view = ui.PlatformDispatcher.instance.views.first;
logicalSize ??= view.physicalSize / view.devicePixelRatio;
imageSize ??= view.physicalSize;
// assert(logicalSize.aspectRatio == imageSize.aspectRatio);
final RenderView renderView = RenderView(
view: view,
child: RenderPositionedBox(alignment: Alignment.center, child: repaintBoundary),
configuration: ViewConfiguration(
size: logicalSize,
devicePixelRatio: 1.0,
),
);
final PipelineOwner pipelineOwner = PipelineOwner();
final BuildOwner buildOwner = BuildOwner(focusManager: FocusManager());
pipelineOwner.rootNode = renderView;
renderView.prepareInitialFrame();
final RenderObjectToWidgetElement<RenderBox> rootElement = RenderObjectToWidgetAdapter<RenderBox>(
container: repaintBoundary,
child: widget,
).attachToRenderTree(buildOwner);
buildOwner.buildScope(rootElement);
await Future.delayed(waitToRender);
buildOwner.buildScope(rootElement);
buildOwner.finalizeTree();
pipelineOwner.flushLayout();
pipelineOwner.flushCompositingBits();
pipelineOwner.flushPaint();
final ui.Image image = await repaintBoundary.toImage(pixelRatio: imageSize.width / logicalSize.width);
final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
return byteData!.buffer.asUint8List();
}
Future<BitmapDescriptor> getCustomIcon() async {
return SizedBox(
height: 200,
width: 200,
child: Image.asset("temp image"),
).toBitmapDescriptor();
}
List<Marker> markerList = <Marker>[];
markerList.add(
Marker(
markerId: const MarkerId("MarkerId"),
position: LatLng(21.000000, 72.000000),
icon: await getCustomIcon(),
),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment