当我当时尝试使用火焰引擎加载base64图像时,出现以下错误我用火焰:^ 0.27.0

问题描述

当我当时使用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来以正确的方式为您完成所有操作。并且从不使渲染或更新方法异步;)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...