Back

Jul 11, 2024

Jul 11, 2024

Flutter Gooey Blobs

Learn how to make gooey blobs with custom painter in Flutter, and how you might be able to use them in your projects.

Flutter Gooey Blobs with CustomPainter
Flutter Gooey Blobs with CustomPainter
Flutter Gooey Blobs with CustomPainter

https://youtu.be/smPos0mJvh8

Have you ever seen these gooey blobs on the internet?

CustomPainter gooey blobs interacting with each other.

They look kinda cool, right? Have you ever thought it would be really cool to create something like this in Flutter?

A few days ago, Twitter user @double__glitch demonstrated creating gooey blobs in Figma. Seeing his technique reminded me of drawing something on a canvas, which led to me thinking about CustomPainter, and I thought, “I can do that! Somehow...”

After an hour or so, I did manage to re-create it in Flutter! Here’s how:


Why CustomPainter?

As I said earlier, the technique shown by @double__glitch is like drawing on a canvas. CustomPainter serves exactly that purpose. It provides you with set of APIs ranging from drawing shapes on a canvas to adding layer composite effects, combining image filters, blend modes, and more.

CustomPainter various effects.

We should be able to do this in Flutter, too! If you aren’t aware, Flutter converts your widget layers into a set of canvas painting instructions as part of the rendering pipeline. Somewhere down the line, these instructions are rendered on the screen.

Before diving into it, here’s something that you’ll need to know to achieve this effect:

saveLayer meme.

saveLayer

saveLayer allows you to create composite effects on canvas. Normally each canvas instruction is painted individually, thus applying composite effects on a group of shapes. With saveLayer, you can group those shapes and apply an effect on those as one single layer on the canvas.

canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), paint);
// drawing instructions here are grouped together. 
canvas.restore();

Save this code

saveLayer takes the size of the layer and a Paint object. Any canvas instructions called after calling saveLayer will be grouped, and once you call canvas.restore, that group will be flattened out into a layer on which the Paint object’s image filters and blend modes will be applied.

Now, back to creating our gooey blobs!


Adding Blurred Circles

We’ll use the canvas.drawCircle() to draw two circles on the canvas and add a blur filter to the layer using saveLayer.

import 'dart:ui';
import 'package:flutter/material.dart';
class BlobsView extends StatefulWidget {
  const BlobsView({super.key});
  @override
  State createState() => _BlobsViewState();
}
class _BlobsViewState extends State {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CustomPaint(
          painter: _BlobsPainter(),
          size: MediaQuery.of(context).size,
        ),
      ),
    );
  }
}
class _BlobsPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final blackCirclesPainter = Paint()
      ..color = Colors.black
      ..style = PaintingStyle.fill;
    final blurLayerPaint = Paint()
      ..color = const Color(0xff808080)
      ..style = PaintingStyle.fill
      ..imageFilter = ImageFilter.blur(
        sigmaX: 10,
        sigmaY: 10,
        tileMode: TileMode.decal,
      );
    canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), blurLayerPaint);
    canvas.drawCircle(Offset(size.width / 2 - 50, size.height / 2), 70, blackCirclesPainter);
    canvas.drawCircle(Offset(size.width / 2 + 50, size.height / 2), 60, blackCirclesPainter);
    canvas.restore();
  }
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

Save this code

Here’s how it looks. Nothing fancy right now.

Flutter animations showing two blurry blobs.


Adding a colorDodge Layer

Next, we’ll add certain layers on top of our canvas with specific blend mode applied to them. The blend mode will specify how the layer should be composed with its background. In this article, we won’t dive deep into how these blend modes work, but if you’re curious, I would recommend reading these w3 docs on the different blend modes mentioned in this article and how they work.

First is the colorDodge layer. We’ll achieve this by creating a rectangle, giving it a bright color like Color(0xff808080), and setting its blend mode to BlendMode.colorDodge.

This will go right after the canvas.restore call:

canvas.drawRect(
      Rect.fromCenter(center: Offset(size.width / 2, size.height / 2), width: size.width, height: size.height),
      Paint()
        ..color = const Color(0xff808080)
        ..style = PaintingStyle.fill
        ..blendMode = BlendMode.colorDodge,
    );

Save this code

Now we get something interesting.

Blobs are now clearer.

colorDoge is one of the blend modes that can be used to brighten the destination image (our canvas in this case) with respect to to the source image (blend mode layer). It basically brightens the brighter areas and adds more contrast and saturation to them. In our case, it helps create sharper outlines for our circles, replacing the blurred outlines. Darker areas of the destination image aren’t affected as much as the brighter areas.


Adding a colorBurn Layer

Now we’ll add a colorBurn layer on top of our whole canvas. Similar to what we did earlier, we’ll create a rectangle, make it black, and set its blend mode to BlendMode.colorBurn.

canvas.drawRect(
      Rect.fromCenter(center: Offset(size.width / 2, size.height / 2), width: size.width, height: size.height),
      Paint()
        ..color = Colors.black
        ..style = PaintingStyle.fill
        ..blendMode = BlendMode.colorBurn,
    );

Save this code

We’re getting close!

Blobs now have no blur.

colorBurn is basically the opposite of colorDodge. It darkens the destination image with respect to the source image. With this, the inside blurred areas of the circles become completely black, creating a sharp, gooey shape.


Adding a Gradient layer

As before, we’ll add a gradient layer with a blend mode set to screen. Setting the blend mode to screen will compose this layer as an overlay on top of our gooey shapes, excluding the white areas of the canvas.

canvas.drawRect(
      Rect.fromCenter(center: Offset(size.width / 2, size.height / 2), width: size.width, height: size.height),
      Paint()
        ..style = PaintingStyle.fill
        ..shader = const RadialGradient(
          colors: [Colors.yellow, Colors.pink],
        ).createShader(
          Rect.fromCenter(
            center: Offset(size.width / 2, size.height / 2),
            width: size.width,
            height: size.height,
          ),
        )
        ..blendMode = BlendMode.screen,
    );

Save this code

With that, our gooey blobs are ready! 🎉

Gooey blobs are now interactive.

This is the final version after adding drag controls.

We finally have gooey blobs in Flutter and that wasn’t crazy hard to do. It’s interesting how using composite effects with various blend modes can help you create some interesting visuals like this.

Use these blobs cautiously though :)


Conclusion

You can find the source code for these gooey blobs here among some of my other creative work. Feel free to poke around and play with them :)

Rutvik Tak headshot.
Rutvik Tak headshot.

Written by

Written by

Rutvik Tak

Rutvik Tak

SHARE

SHARE

Title

Title

our newsletter

Sign up for The Pieces Post

Check out our monthly newsletter for curated tips & tricks, product updates, industry insights and more.

our newsletter

Sign up for The Pieces Post

Check out our monthly newsletter for curated tips & tricks, product updates, industry insights and more.

our newsletter

Sign up for The Pieces Post

Check out our monthly newsletter for curated tips & tricks, product updates, industry insights and more.