Flutter - How To Draw An Image On Canvas Using Drawimage Method
Solution 1:
This simple utility method returns a Future<UI.Image>
given the image asset's path:
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;
}
Solution 2:
ui.Codec has a method getNextFrame()
which returns a Future<FrameInfo>
(you should probably have logic around how many frames but if you know it's always a normal picture you could skip that.) FrameInfo
has an image
property which is the Image you need.
EDIT: looking at the code you have in the post, it's not clear where you're doing what. Is that all defined within the CustomPainter.paint
method? If so, you'd definitely have issues because you can only use the canvas
for the duration of the paint
call; you should not retain any references to it outside of the function (which would include any asynchronous call).
I'd recommend using a FutureBuilder so that you only draw on the canvas once you've added the image.
That would look something like this:
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 herevar 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: returnnew Text('Image loading...');
default:
if (snapshot.hasError)
returnnew Text('Error: ${snapshot.error}');
else// ImageCanvasDrawer would be a (most likely) statless widget// that actually makes the CustomPaint etcreturnnew ImageCanvasDrawer(image: snapshot.data)
}
},
)
Solution 3:
classImagePainterextendsCustomPainter {
List<ui.Image> images = newList<ui.Image>();
ImagePainter(
{Key key,
@requiredthis.noOfSlice,
@requiredthis.images,
@requiredthis.rotation,
this.boxfit = BoxFit.contain})
:
// : path = new Path()// ..addOval(new Rect.fromCircle(// center: new Offset(75.0, 75.0),// radius: 40.0,// )),
tickPaint = newPaint() {
tickPaint.strokeWidth = 2.5;
}
finalint noOfSlice;
final tickPaint;
final BoxFit boxfit;
ui.ImageByteFormat img;
ui.Rect rect, inputSubrect, outputSubrect;
Size imageSize;
FittedSizes sizes;
double radius,
rotation = 0.0,
_x,
_y,
_angle,
_radiun,
_baseLength,
_imageCircleradius,
_incircleRadius,
_imageOffset = 0.0,
_imageSizeConst = 0.0;
@overridevoidpaint(ui.Canvas canvas, ui.Size size) {
print("image data:: $images");
radius = size.width / 2;
_angle = 360 / (noOfSlice * 2.0);
_radiun = (_angle * pi) / 180;
_baseLength = 2 * radius * sin(_radiun);
_incircleRadius = (_baseLength / 2) * tan(_radiun);
if (noOfSlice == 4) {
_imageOffset = 30.0;
_imageSizeConst = 30.0;
_x = 8.60;
_y = 4.10;
} elseif (noOfSlice == 6) {
_imageOffset = 20.0;
_x = 10.60;
_y = 5.60;
} elseif (noOfSlice == 8) {
_imageOffset = 40.0;
_imageSizeConst = 30.0;
_x = 12.90;
_y = 6.60;
}
//print("circle radisu:: $_incircleRadius");
canvas.save();
canvas.translate(size.width / 2, size.height / 2);
canvas.rotate(-rotation);
intincr=0;
rect = ui.Offset((size.width / _x), size.width / _y) & newSize(0.0, 0.0);
imageSize = newSize(size.width * 1.5, size.width * 1.5);
sizes = applyBoxFit(
boxfit,
imageSize,
newSize(size.width / 2 * .50 + _incircleRadius * .8,
size.width / 2 * .50 + _incircleRadius * .8));
inputSubrect =
Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
outputSubrect = Alignment.center.inscribe(sizes.destination, rect);
if (images.length == noOfSlice && images.isNotEmpty)
for (vari=1; i <= noOfSlice * 2; ++i) {
if (i % 2 != 0) {
canvas.drawLine(
newOffset(0.0, 0.0),
newOffset(0.0, size.width / 2 - 4.2),
tickPaint,
);
} else {
canvas.save();
canvas.translate(-0.0, -((size.width) / 2.2));
ui.Imageimage= images[incr];
if (image != null) {
canvas.drawImageRect(
image, inputSubrect, outputSubrect, newPaint());
}
canvas.restore();
incr++;
}
canvas.rotate(2 * pi / (noOfSlice * 2.0));
}
canvas.restore();
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
returnfalse;
}
}
Post a Comment for "Flutter - How To Draw An Image On Canvas Using Drawimage Method"