问题描述
当我当时使用aync await方法时,它可以正常工作,但是当我尝试将图像加载到Flame的组件类中时,出现错误:
我创建了一个Background类,该类扩展了火焰引擎的组件类。现在,我正在尝试使用then
函数加载base64图像,但是出现错误,但是当我使用异步await
方法进行图像加载时,它可以正常工作。
class Background extends Component with Resizable {
static final Paint _paint = Paint();
Size imageSize = Size(411.42857142857144,822.8571428571429);
@override
void render(Canvas c) {
Rect myRect = const Offset(0.0,0.0) & Size(size.width,size.height);
Flame.images.fromBase64('demo',imageBase).then((value) {
paintimage(canvas: c,rect: myRect,image: value);
});
}
@override
void update(double t) {
// Todo: implement update
}
void paintimage({
@required Canvas canvas,@required Rect rect,@required image.Image image,String debugImageLabel,double scale = 1.0,ColorFilter colorFilter,BoxFit fit,Alignment alignment = Alignment.center,Rect centerSlice,ImageRepeat repeat = ImageRepeat.norepeat,bool flipHorizontally = false,bool invertColors = false,FilterQuality filterQuality = FilterQuality.low,bool isAntiAlias = false,}) {
if (rect.isEmpty) return;
Size outputSize = rect.size;
Size inputSize = Size(image.width.todouble(),image.height.todouble());
Offset sliceBorder;
if (centerSlice != null) {
sliceBorder = Offset(
centerSlice.left + inputSize.width - centerSlice.right,centerSlice.top + inputSize.height - centerSlice.bottom,);
outputSize = outputSize - sliceBorder as Size;
inputSize = inputSize - sliceBorder as Size;
}
fit ??= centerSlice == null ? BoxFit.scaleDown : BoxFit.fill;
assert(centerSlice == null || (fit != BoxFit.none && fit != BoxFit.cover));
final FittedSizes fittedSizes =
applyBoxFit(fit,inputSize / scale,outputSize);
final Size sourceSize = fittedSizes.source * scale;
Size destinationSize = fittedSizes.destination;
if (centerSlice != null) {
outputSize += sliceBorder;
destinationSize += sliceBorder;
}
// Output size is fully calculated.
if (repeat != ImageRepeat.norepeat && destinationSize == outputSize) {
repeat = ImageRepeat.norepeat;
}
final Paint paint = Paint()..isAntiAlias = isAntiAlias;
if (colorFilter != null) paint.colorFilter = colorFilter;
if (sourceSize != destinationSize) {
paint.filterQuality = filterQuality;
}
paint.invertColors = invertColors;
final double halfWidthDelta =
(outputSize.width - destinationSize.width) / 2.0;
final double halfheightDelta =
(outputSize.height - destinationSize.height) / 2.0;
final double dx = halfWidthDelta +
(flipHorizontally ? -alignment.x : alignment.x) * halfWidthDelta;
final double dy = halfheightDelta + alignment.y * halfheightDelta;
final Offset destinationPosition = rect.topLeft.translate(dx,dy);
final Rect destinationRect = destinationPosition & destinationSize;
final bool needSave = repeat != ImageRepeat.norepeat || flipHorizontally;
if (needSave) canvas.save();
if (repeat != ImageRepeat.norepeat) canvas.clipRect(rect);
if (flipHorizontally) {
final double dx = -(rect.left + rect.width / 2.0);
canvas.translate(-dx,0.0);
canvas.scale(-1.0,1.0);
canvas.translate(dx,0.0);
}
if (centerSlice == null) {
final Rect sourceRect = alignment.inscribe(
sourceSize,Offset.zero & inputSize,);
if (repeat == ImageRepeat.norepeat) {
canvas.drawImageRect(image,sourceRect,destinationRect,paint);
} else {
print("no repet else");
}
}
//if (needSave) canvas.restore();
}
}
解决方法
这是完全不可接受的:
@override
void render(Canvas c) {
Rect myRect = const Offset(0.0,0.0) & Size(size.width,size.height);
Flame.images.fromBase64('demo',imageBase).then((value) {
paintImage(canvas: c,rect: myRect,image: value);
});
}
渲染方法必须是 sync 。它需要立即渲染一个画布对象。您无法在此处进行异步操作!当然,画布将被丢弃,只能使用一帧。渲染方法被称为每一帧,并且必须快速且短暂。当实际加载图像时,您将不再有权使用画布,因为将完成整个渲染周期。它已经在屏幕上渲染了!您无法改变过去!那没有道理。
您需要做的是将图像加载到其他位置,并在加载后有条件地渲染。将加载移至您的构造函数中:
Flame.images.fromBase64('demo',imageBase).then((value) {
this.image = value;
});
然后在render方法上,有条件地渲染:
@override
void render(Canvas c) {
Rect myRect = const Offset(0.0,size.height);
if (this.image != null) {
paintImage(canvas: c,image: this.image);
}
}
通过在组件上创建图像字段。还可以考虑使用SpriteComponent
来以正确的方式为您完成所有操作。并且从不使渲染或更新方法异步;)