Flutter-如何使用drawImage方法在Canvas上绘制图像

And*_*ade 7 android canvas dart flutter

我正在尝试将图像文件绘制到画布中以在Flutter中组成我的小部件。

我确实遵循了画布文档,但是没有成功。O Image docs,说:

要获取Image对象,请使用InstantiateImageCodec。

我确实尝试过使用instantiateImageCodec方法,但是我只是得到一个Codec实例,而不是图像

如何使用ui.Image实例在画布上绘制的正确方法 canvas.drawImage

这是我的代码的摘要:

Future<ui.Codec> _loadImage(AssetBundleImageKey key) async {
  final ByteData data = await key.bundle.load(key.name);
   if (data == null)
  throw 'Unable to read data';
   return await ui.instantiateImageCodec(data.buffer.asUint8List());
}

final Paint paint = new Paint()
  ..color = Colors.yellow
  ..strokeWidth = 2.0
  ..strokeCap = StrokeCap.butt
  ..style = PaintingStyle.stroke;

var sunImage = new ExactAssetImage("res/images/grid_icon.png");

sunImage.obtainKey(new ImageConfiguration()).then((AssetBundleImageKey key){
  _loadImage(key).then((ui.Codec codec){
    print("frameCount: ${codec.frameCount.toString()}");
    codec.getNextFrame().then((info){
      print("image: ${info.image.toString()}");
      print("duration: ${info.duration.toString()}");
      canvas.drawImage(info.image, size.center(Offset.zero), paint);
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

bon*_*nyz 9

这个简单的实用程序方法返回Future<UI.Image>给定的图像资产的路径:

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as UI;

import 'package:flutter/services.dart';

Future<UI.Image> loadUiImage(String imageAssetPath) async {
  final ByteData data = await rootBundle.load(imageAssetPath);
  final Completer<UI.Image> completer = Completer();
  UI.decodeImageFromList(Uint8List.view(data.buffer), (UI.Image img) {
    return completer.complete(img);
  });
  return completer.future;
}
Run Code Online (Sandbox Code Playgroud)


rmt*_*zie 5

ui.Codec有一个getNextFrame()返回a 的方法Future<FrameInfo>(您可能应该对多少帧有逻辑,但是如果您知道它始终是正常图片,则可以跳过)。它FrameInfo具有一个image属性,即您需要的Image。

编辑:查看您在帖子中的代码,不清楚您在哪里做什么。这是在CustomPainter.paint方法中定义的吗?如果是这样,您肯定会遇到问题,因为您只能canvaspaint通话期间使用。您不应在函数之外保留对它的任何引用(这将包括任何异步调用)。

我建议使用FutureBuilder,以便仅在添加图像后才在画布上绘制。

看起来像这样:

Future<Image> _loadImage(AssetBundleImageKey key) async {
  final ByteData data = await key.bundle.load(key.name);
  if (data == null)
    throw 'Unable to read data';
  var codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
  // add additional checking for number of frames etc here
  var frame = await codec.getNextFrame();
  return frame.image;
}

new FutureBuilder<Image>(
  future: loadImage(....), // a Future<String> or null
  builder: (BuildContext context, AsyncSnapshot<Image> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.waiting: return new Text('Image loading...');
      default:
        if (snapshot.hasError)
          return new Text('Error: ${snapshot.error}');
        else
          // ImageCanvasDrawer would be a (most likely) statless widget
          // that actually makes the CustomPaint etc
          return new ImageCanvasDrawer(image: snapshot.data)
    }
  },
)
Run Code Online (Sandbox Code Playgroud)