Flutter Generative Art: The Easy Way

Using the intricacy of basic math to create other-worldly structures

Deven Joshi
6 min readMay 14, 2020

Oscar Wilde: “All art is quite useless.” — but maybe useless is what we need right now.

Generative art in Flutter is still relatively new. However, there is a lot of fascinating artwork coming from all around the world with different techniques for creating it. It is safe to say Robert Felker started the trend with his dArt series and looking at his examples, I thought of creating a way of doing that of my own. With the extra time from the global situation, I went ahead.

An example from the d_Art series

There were a few problems: I’m horrible at all things art, I’m a bad chooser of colour combinations, and I haven’t gone as deep into the CustomPaint API as I would have liked to. So I decided to go with: basic trigonometric math functions and random colours so I don’t have to choose.

Trial and error

My attempt at creating an artwork was going to be rather simple: Use (A LOT OF) points on a Canvas with varying radii and random colors and position them with basic math. This worked out well enough… but they came out rather boring and symmetrical.

For just a last attempt, I tried to alter how my distance parameter worked and something I didn’t expect happened: they actually turned out really well.

At this point I felt like I got at least SOMETHING out of multiple tries to get it going. But, for some reason, I felt like I could modify it to be even better. So I tried and I did not regret doing it:

The most fascinating thing about this was that the working code was only ~10 lines and everything else was boilerplate! The only thing it used were basic sin, cos, tan, atan functions. (Code in next section)

When I added more iterations and mixed in more trigonometric functions, it led to pictures like this:

I created several other pictures which I’ll have at the end. First, let’s look at the code, which is surprisingly short.

Code

(CodePen link at the end of the section)

The first part of the code is the basic setup of the app which instantiates a CustomPaint and uses a CustomPainter to paint the artwork.

import ‘dart:math’;
import ‘dart:ui’;
import ‘package:flutter/material.dart’;void main() => runApp(MyApp());class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter Demo’,
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: Container(
child: CustomPaint(
painter: DemoPainter(),
child: Container(),
),
),
),
);
}
}

Nothing significant here. Now we set up the CustomPainter:

class DemoPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// We paint here
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}

The paint() method contains the actual things we paint the artwork with. Let’s explore:

First, we take a variable distance to store distances to plot our points at. Although the variable was meant to store distance, after modifications, it only correlates with distance and is not the physical distance.

double distance = 0.0;// Choose a random color from a defined color list
Color c = colors[Random().nextInt(colors.length)].color;

We also choose a random color to paint all dots with. We will change color over multiple paint iterations.

Now we actually paint all dots (circles) on the screen. The geometric structures visible in the art is determined by the trigonometric functions used here in the drawCircle() method.

 for (double i = 0; i < 1000; i = i + 0.01) { canvas.drawCircle(

Offset(
(size.width / 2) +
(distance * atan(distance) * sin(distance) * cos(distance)),
(size.height / 2) +
(distance * cos(distance) * sin(distance) * tan(distance)),
),
// Change this for changing radius in different iterations
5.0 — (0.5 * (initIter — iter)),
Paint()..color = c,
);
// Change the “0.1” for varying point distances
distance = distance + (0.2 + (0.1 * initIter — iter));
}

We vary distance after every dot is painted.

Note that initIter and iter are variables used to shrink radii of dots over multiple paint iterations.

The last thing to do is have multiple iterations of painting, so instead of a loop, we’ll use a separate function with recursion.

// Recursive function which draws iterations from iter to 0
void renderStructure(Canvas canvas, Size size, int iter, int initIter) {
if (iter == 0) {
return;
}
double distance = 0.0;
Color c = colors[Random().nextInt(colors.length)].color; for (double i = 0; i < 1000; i = i + 0.01) {
canvas.drawCircle(
Offset(
(size.width / 2) +
(distance * atan(distance) * sin(distance) * cos(distance)),
(size.height / 2) +
(distance * cos(distance) * sin(distance) * tan(distance)),
),
5.0 — (0.5 * (initIter — iter)), Paint()..color = c,
);
distance = distance + (0.2 + (0.1 * initIter — iter));
}
// Recursively call the next iteration
renderStructure(canvas, size, iter — 1, initIter);
}

And voila! All we do to change colors is reload the app. All we do to explore new structures possible is modify the lines:

(distance * atan(distance) * sin(distance) * cos(distance))

And

(distance * cos(distance) * sin(distance) * tan(distance))

Add and remove the trigonometric functions here to see various kinds of results! Here are a few more:

CodePen link for viewing and running code:

Bonus: Animated Art!

Fresh off the art high, I set myself another challenge: Animate the artwork…Fine, I didn’t set the challenge, but other people were really curious how it would look. Took me an hour and the result was better than I hoped for:

And another one:

Animated CodePen link:

Bonus Part 2: Wallpapers!

I just whipped up a few of these as wallpapers if anyone wanted to try it out:

That’s it for this article! I hope you enjoyed it and leave a few claps if you did. Follow me for more Flutter articles and comment for any feedback you might have about this article.

My Twitter and GitHub for following my Flutter obsession

A few other things I wrote

--

--

Deven Joshi

Google Developer Expert, Flutter | Technical Writer | Speaker