如何在颤振中使用混合混合模式?
Posted
技术标签:
【中文标题】如何在颤振中使用混合混合模式?【英文标题】:How to use mix blend mode in flutter? 【发布时间】:2020-10-18 13:56:01 【问题描述】:我尝试了似乎仅适用于颜色的混合模式,即 colorblendmode。有什么办法可以实现mix-blend-mode as of CSS?
Stack(
children: <Widget>[
Image.asset(
"asset/text.PNG",
height: double.maxFinite,
width: double.maxFinite,
fit: BoxFit.fitHeight,
color: Colors.red,
colorBlendMode: BlendMode.multiply,
),
Image.asset("asset/face.jpg",
width: double.maxFinite,
fit: BoxFit.fitHeight,
color: Colors.red,
colorBlendMode: BlendMode.multiply),
],
),
这会产生如下结果: The output of code above
我想得到什么 Output from CSS
【问题讨论】:
不知道。但也许您可以尝试使用 BlendMode.试试ShaderMask。BlendModes
使用示例:
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
Future<ui.Image> loadUiImage(String imageAssetPath) async
final data = await rootBundle.load(imageAssetPath);
final completer = Completer<ui.Image>();
ui.decodeImageFromList(Uint8List.view(data.buffer), completer.complete);
return completer.future;
@override
Widget build(BuildContext context)
return FutureBuilder<ui.Image>(
future: loadUiImage('assets/cara_img.png'),
builder: (context, img)
return img.hasData
? ShaderMask(
blendMode: BlendMode.colorDodge,
shaderCallback: (bounds) => ImageShader(
img.data,
TileMode.clamp,
TileMode.clamp,
Matrix4.identity().storage,
),
child: Image.asset('assets/code.png'),
)
: Container(
color: Colors.red,
height: 100,
width: 100,
child: Text('loading'),
);
);
code.png: cara_img.png:
结果:
【讨论】:
这是一个很棒的解决方案,但它有点笨重,而且您必须异步加载图像。为什么不使用 RenderObjects?【参考方案2】:使用 RenderProxyBox 和一些绘画,我能够在 CSS 网站上重新创建确切的示例,而无需在 Flutter 代码中异步加载图像。
使用 CSS 的图像(左)与使用 Flutter 的图像(右)。
Read the article I wrote about this here
首先,创建一个 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 示例完全相同。
【讨论】:
没问题@ReikoDev。如果您有兴趣,我可能应该链接到我写的关于它的文章。 wilsonwilson.dev/articles/css-style-blending-using-flutter 再次感谢@Wilson!我正在玩画布,这很有帮助!一个问题,当你有一个自定义布局(例如在 Illustrator 上制作)时,像 ibb.co/WV3JxZd 这样的东西,你使用哪种方法让它在颤振上变得真实? @ReikoDev 哇哦,很多很多的定制油漆。不过,我不相信用颤振构建一切是一个现实或好主意。对于星星、窗帘、横幅以及可能的容器之类的东西,最好使用原始设计文件。对于诸如进度条之类的反应组件,您可以安全地使用自定义油漆:D 哦,我明白了!再次感谢威尔逊!!以上是关于如何在颤振中使用混合混合模式?的主要内容,如果未能解决你的问题,请参考以下文章
SKEmitterNode 如何在不同背景下使用混合模式“添加”保持相同的效果