Created
April 7, 2024 23:33
-
-
Save kururu-abdo/ea9bda4adbdd0c2d21060890e2ed2b83 to your computer and use it in GitHub Desktop.
flutter_map_custom_marker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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