Recreating Stunning Strange Attractor, Fibonacci Sphere & Galaxy Animations in Flutter with Pure Dart

This article explains how to implement three complex visual effects—Strange Attractor, Fibonacci Sphere, and Galaxy animations—in Flutter using only Dart code, covering the underlying differential equations, Euler integration, 3D‑to‑2D projection, rotation, perspective, performance optimizations, and solutions to common GPU tile‑artifact issues.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Recreating Stunning Strange Attractor, Fibonacci Sphere & Galaxy Animations in Flutter with Pure Dart

Overview

This article demonstrates how to implement three mathematically‑driven visual effects in Flutter using pure Dart: a Strange Attractor animation, a Fibonacci Sphere, and a Galaxy (star‑nebula) scene. All effects rely on differential equations, geometric algorithms, and GPU‑accelerated rendering.

Strange Attractor Animation

The animation visualises classic chaotic systems by integrating their differential equations with Euler integration and projecting the resulting 3D particle positions onto the 2D Canvas.

Key Steps

Mathematical model : Convert the attractor’s differential equations into Dart code and update particle velocity with Euler integration in a method such as _updatePhysics.

3D‑to‑2D projection : Apply a simple perspective projection (u, v) = f(x, y, z) and rotate the coordinate system to give depth.

newPosition = oldPosition + velocity(dx, dy, dz) * dt

Halvorsen Attractor

const a = 1.4;
dx = -a * p.x - 4 * p.y - 4 * p.z - (p.y * p.y);
dy = -a * p.y - 4 * p.z - 4 * p.x - (p.z * p.z);
dz = -a * p.z - 4 * p.x - 4 * p.y - (p.x * p.x);

Lorenz Attractor

dx = sigma * (p.y - p.x);
dy = p.x * (rho - p.z) - p.y;
dz = p.x * p.y - beta * p.z;

Aizawa Attractor

dx = (p.z - b) * p.x - d * p.y;
dy = d * p.x + (p.z - b) * p.y;
dz = c + a * p.z - (p.z * p.z * p.z) / 3 - (p.x * p.x + p.y * p.y) * (1 + e * p.z) + f * p.z * (p.x * p.x * p.x);

Sprott B Attractor

dx = a * p.y * p.z;
dy = p.x - p.y;
dz = b - p.x * p.y;

Stability Fixes

Boundary check (e.g., if (p.x.abs() > 50 || p.x.isNaN) …)

Respawn logic ( _resetSingleParticle(p))

Reduced time step (e.g., dt = 0.004 for Halvorsen)

Fibonacci Sphere Animation

Points are distributed uniformly on a sphere using the golden‑angle algorithm, then the sphere is rotated and rendered with perspective.

Algorithm

final double goldenAngle = pi * (3 - sqrt(5)); // ~137.5°
for (int i = 0; i < numPoints; i++) {
  double y = 1 - (i / (numPoints - 1)) * 2; // uniform y
  double radiusAtY = sqrt(1 - y * y);
  double theta = goldenAngle * i;
  double x = cos(theta) * radiusAtY;
  double z = sin(theta) * radiusAtY;
  // apply rotation matrix, then perspective
}

Rotation & Perspective

double x1 = x * cos(rotationY) - z * sin(rotationY);
double z1 = x * sin(rotationY) + z * cos(rotationY);

double focalLength = 800.0;
double perspective = focalLength / (focalLength - pz);
double screenX = center.dx + px * perspective;
double screenY = center.dy + py * perspective;
double pointSize = basePointSize * perspective;

Visual Enhancements

Wobble wave using sin(time) and vertical phase shift + y * 4.

Trails: draw circles when trails == 0, draw lines when trails > 0 with length scaled by perspective.

Galaxy (Star‑Nebula) Animation

Extends the Sprott B attractor with additional forces to simulate a galaxy‑like structure.

Physical Model

Central attraction provides a basic centripetal force.

Rotating‑rod force creates a bipolar field.

Accretion disc: particles spawn on an outer ring and lose energy via velocity *= 0.9995.

Turbulence Function

Offset getTurbulence(int i, double phase, double t) {
  double speed = 2.0;
  double dx = 0.06 * sin(t * speed + phase) + 0.03 * cos(t * speed * 2.3 + i * 0.1);
  double dy = 0.06 * cos(t * speed * 1.5 + phase) + 0.03 * sin(t * speed * 1.9 + i * 0.1);
  double rotAngle = t * 0.5 * (i % 2 == 0 ? 1 : -1);
  double rx = dx * cos(rotAngle) - dy * sin(rotAngle);
  double ry = dx * sin(rotAngle) + dy * cos(rotAngle);
  return Offset(rx, ry);
}

Rendering Optimizations

Store particle data in Float32List for compact memory layout.

Batch‑draw 30 000 particles with canvas.drawRawPoints using BlendMode.plus to create bright overlapping regions.

Tile‑Artifact Problem & Workarounds

When blending a gradient from orange to transparent, uninitialized GPU tiles produced dark squares. Attempts such as TileMode.decal, adjusting transparent colors, and switching BlendMode (Screen/Plus) did not eliminate the artifacts. The final practical workaround layered multiple phase‑shifted wobble animations, varying size and scale over time, which avoided the problematic gradient while preserving the glowing effect.

Resources

Full source code: https://github.com/CarGuo/gsy_flutter_demo

DARTFlutteranimationGraphicsGPUMathematicsattractor
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.