How to create an image from a widget in Flutter-web?

2,396

Solution 1

toImage() works if you put --dart-define=FLUTTER_WEB_USE_SKIA on flutter build web arguments.

The method works locally without this argument.

I found this solution after seeing the crop package documentation, which also makes use of toImage()

EDIT

I found some problems when accessing the application through the iPhone, the generation of images from a widget works, but some animations that I have in the project stopped working.

I found this question and i will make some tests only using the argument --dart-define=FLUTTER_WEB_AUTO_DETECT=true to see if works on desktop, android and iOS correctly with Flutter web.

EDIT 2

After some testing on MacOs, the toImage() method works correctly as well.

Solution 2

The repaintBoundary.toImage functionality depends on Scene.toImage which according to comments in issue #42767 is not yet implemented for Web.
That issue is also currently deprioritized.

Share:
2,396
Alex
Author by

Alex

Updated on December 18, 2022

Comments

  • Alex
    Alex over 1 year

    To display custom widgets on google maps google_maps_flutter I use a very convenient function that translates any Widget (including those containing images) into an Image, which I then translate into the Uint8List I need. It works great on iOS and Android.

    Future createImageFromWidget( Widget widget){
      final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();
      final RenderView renderView = RenderView(
        child: RenderPositionedBox(alignment: Alignment.center, child: repaintBoundary),
        configuration: ViewConfiguration(size: const Size.square(300.0), devicePixelRatio: ui.window.devicePixelRatio),
        window: null,
      );
    
      final PipelineOwner pipelineOwner = PipelineOwner()..rootNode = renderView;
      renderView.prepareInitialFrame();
    
      final BuildOwner buildOwner = BuildOwner(focusManager: FocusManager());
      final RenderObjectToWidgetElement<RenderBox> rootElement = RenderObjectToWidgetAdapter<RenderBox>(
        container: repaintBoundary,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: IntrinsicHeight(child: IntrinsicWidth(child: widget)),
        ),
      ).attachToRenderTree(buildOwner);
    
      buildOwner..buildScope(rootElement)..finalizeTree();
      pipelineOwner..flushLayout()..flushCompositingBits()..flushPaint();
    
      return repaintBoundary.toImage(pixelRatio: ui.window.devicePixelRatio)
        .then((image) => image.toByteData(format: ui.ImageByteFormat.png))
        .then((byteData) => byteData.buffer.asUint8List());
    }
    

    But unfortunately, when I try to use this function on the Web I get the following error:

    Unsupported operation: toImage is not supported on the Web

    Now Flutter has support for Image.toByteData and Picture.toImage #20750, but I can't figure out how this can be used in my case.

    Actually the question is - how to remake this function so that it would work on the Web too?

    Thank you, I will be glad to any ideas

  • Alex
    Alex over 3 years
    Thanks for the cue! But in this PR there is no intention to make the repaintBoundary.toImage maybe the Scene.toImage.