I have tried the blend mode that seems to be working for only color i.e colorblendmode. Is there any way to achieve the 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),
],
),
This results in something like: The output of code above
What i want to get Output from CSS
BlendMode blendMode. A blend mode to apply when a shape is drawn or a layer is composited. The source colors are from the shape being drawn (e.g. from Canvas. drawPath) or layer being composited (the graphics that were drawn between the Canvas.
operator + final combinedColor = colorA + addendColor; Note that the way I created the extension, the addend (here addendColor ) will be the background. You can change this by reversing (this, other) to (other, this) .
mix-blend-mode is a CSS property that defines how the content of an element should blend with the content of the element's parent and its background. With this, you can create nice blends and colors for parts of an element's content depending on its direct background.
difference : this subtracts the darker of the two colors from the lightest color. exclusion : similar to difference but with lower contrast. hue : creates a color with the hue of the content combined with the saturation and luminosity of the background.
Using RenderProxyBox and some painting, I was able to recreate the exact sample on the CSS website without asynchronously loading the image in your Flutter code.
Image using CSS (left) vs image using Flutter(right).
Read the article I wrote about this here
To start, a BlendMask SingleChildRenderObject is created that creates a RenderProxyBox render object called RenderBlendMask is created. The child is painted with a BlendMode and an opacity.
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();
}
}
Now to blend two widgets (Not restricted to images), just add the widget you want to blend above another using a stack, and wrap it in your 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',
),
),
),
],
)),
);
}
}
That produces the image above, and it works exactly like the CSS example.
Try ShaderMask.
BlendModes
Example of use:
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:
Results:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With