使用 RenderProxyBox 和绘图技术,我能够在不异步加载图像的情况下,在 Flutter 代码中精确地重新创建 CSS 网站上的示例。
CSS 中的图像(左)与 Flutter 中的图像(右)。
请阅读我在这方面撰写的文章
首先,创建一个BlendMask SingleChildRenderObject,它创建了一个名为RenderBlendMask的RenderProxyBox渲染对象。使用BlendMode和不透明度对子元素进行绘制。
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
class BlendMask extends SingleChildRenderObjectWidget {
final BlendMode blendMode;
final double opacity;
BlendMask({
@required this.blendMode,
this.opacity = 1.0,
Key key,
Widget child,
}) : super(key: key, child: child);
@override
RenderObject createRenderObject(context) {
return RenderBlendMask(blendMode, opacity);
}
@override
void updateRenderObject(BuildContext context, RenderBlendMask renderObject) {
renderObject.blendMode = blendMode;
renderObject.opacity = opacity;
}
}
class RenderBlendMask extends RenderProxyBox {
BlendMode blendMode;
double opacity;
RenderBlendMask(this.blendMode, this.opacity);
@override
void paint(context, offset) {
context.canvas.saveLayer(
offset & size,
Paint()
..blendMode = blendMode
..color = Color.fromARGB((opacity * 255).round(), 255, 255, 255));
super.paint(context, offset);
context.canvas.restore();
}
}
现在,要混合两个小部件(不仅限于图像),只需使用堆栈将您想要混合的小部件放在另一个小部件上方,并在其中包装您的BlendMode。
class ImageMixer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox.expand(
child: Stack(
children: [
SizedBox.expand(
child: Image.asset(
'images/sky.jpg',
),
),
BlendMask(
opacity: 1.0,
blendMode: BlendMode.softLight,
child: SizedBox.expand(
child: Image.asset(
'images/monkey.jpg',
),
),
),
],
)),
);
}
}
那会生成上面的图片,它的工作方式与CSS示例完全相同。