Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use mix blend mode in flutter?

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

like image 450
sid Avatar asked Jun 28 '20 09:06

sid


People also ask

What is blend mode in flutter?

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.

How do you mix two colors in flutter?

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) .

How does Mix-blend-mode work?

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.

What is the difference between Mix-blend-mode difference and mix blend mode exclusion?

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.


Video Answer


2 Answers

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).

Blendmode CSS vs Flutter

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.

like image 92
Wilson Wilson Avatar answered Oct 22 '22 01:10

Wilson Wilson


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:
code.png cara_img.png:
cara_img.png

Results:
enter image description here enter image description here enter image description here

like image 9
Kherel Avatar answered Oct 22 '22 00:10

Kherel