twinkle_twinkle 0.1.1 copy "twinkle_twinkle: ^0.1.1" to clipboard
twinkle_twinkle: ^0.1.1 copied to clipboard

Composable sparkle, glitter, fireworks, and cinematic transition effects for Flutter.

twinkle_twinkle #

Configurable gradient sparkle, fading or interactive pointer glitter, abstract twinkle fireworks, and directional screen transitions for Flutter.

Open the live Flutter web gallery.

The effects wrap host-owned widgets, accept host styling, and keep their paint layers non-interactive so application controls continue to receive input.

Effects #

Edge sparkle #

EdgeSparkle(
  config: const EdgeSparkleConfig(
    band: EdgeSparkleBand(
      edge: SparkleEdge.bottom,
      extent: 56,
      gradient: LinearGradient(
        colors: [Color(0x00282A46), Color(0x38282A46)],
      ),
    ),
    emitter: SparkleEmitter.cadenced(
      count: 24,
      spacing: .8,
      distribution: SparkleDistribution.golden,
      spawnInterval: Duration(milliseconds: 45),
      burstSize: 3,
    ),
    timeline: SparkleTimeline(
      duration: Duration(seconds: 3),
      initialDelay: Duration(milliseconds: 120),
      repeatDelay: Duration(milliseconds: 240),
      phaseDelay: Duration(milliseconds: 35),
      curve: Curves.easeInOut,
    ),
    motion: SparkleMotion.drift(distance: 12, curve: Curves.easeOut),
    appearance: SparkleAppearance(
      palette: [Colors.indigo, Colors.purple, Colors.pink],
      minSize: 3,
      maxSize: 10,
      opacity: .75,
      hueShift: 30,
      sizeCurve: Curves.easeInOut,
      opacityCurve: Curves.easeInOut,
    ),
    renderer: SparkleRenderer.fourPoint(),
  ),
  child: yourWidget,
)

Each policy is independent and lives in its own public file. Hosts can replace the band, emitter, timeline, motion, appearance, or renderer without subclassing the widget. This controls complete gradients, count and bounded cadence, spacing and distribution, speed and delays, phase timing, motion curves, palette and hue animation, size and opacity curves, and particle shape.

Existing edge, style, density, duration, bandExtent, drift, and gradient arguments remain source compatible. They resolve to the survey-inspired policies when a corresponding explicit policy is absent, so policies can be adopted one at a time.

The built-in four-point renderer uses line and circle canvas primitives so continuous Flutter web animation does not repeatedly record CanvasKit paths. A host-supplied SparkleRenderer remains fully responsible for its own canvas operations.

Fading and interactive glitter #

final glitter = GlitterController();

GlitterTrail(
  controller: glitter,
  config: const GlitterTrailConfig(
    effect: GlitterEffect.trail,
    maximumParticles: 200,
    particleLifetime: Duration(milliseconds: 900),
  ),
  child: yourInteractiveWidget,
)

// Remove every current star.
glitter.clear();

Trail stars shrink and fade over particleLifetime. Select GlitterEffect.interactive for bounded persistent particles that repel from pointer movement and attract while the primary mouse button is held.

GlitterTrail owns its BLoC automatically, or a host can inject and observe one:

final bloc = GlitterBloc(
  config: const GlitterTrailConfig(effect: GlitterEffect.interactive),
);

GlitterTrail(bloc: bloc, child: yourInteractiveWidget)

Each BLoC owns a GlitterParticleRegistry that lazily allocates reusable slots up to maximumParticles. At capacity it recycles the oldest slot, and the trail pauses frame processing whenever no particles are active. Active frames repaint directly from the registry and batch every star through one reusable sprite atlas, without rebuilding the widget subtree for each tick.

The BLoC continues to emit immutable interaction and lifecycle snapshots. For the current per-frame position or fade state, read bloc.registry on demand instead of expecting a new BLoC state for every display refresh.

The overlay uses IgnorePointer, so buttons and other controls remain usable.

Twinkle fireworks #

final fireworks = TwinkleFireworksController();

TwinkleFireworks(
  controller: fireworks,
  config: const TwinkleFireworksConfig(
    capacity: 180,
    gravity: 110,
    drag: .985,
    seed: 29,
    bursts: [
      FireworkBurst(
        origin: Offset(.3, .48),
        style: FireworkBurstStyle.radial,
        particleCount: 40,
      ),
      FireworkBurst(
        origin: Offset(.7, .36),
        delay: Duration(milliseconds: 280),
        style: FireworkBurstStyle.ring,
        particleCount: 48,
      ),
    ],
  ),
  child: FilledButton(
    onPressed: fireworks.fire,
    child: const Text('Complete quiz'),
  ),
)

The radial, ring, and sparkle styles create abstract circle blooms made only from twinkles—there are no rocket illustrations. Each burst independently controls normalized origin, delay, style, count, launch speeds, palette, lifetime, sizes, opacity, and twinkle frequency. Sequence configuration controls duration, capacity, gravity, drag, deterministic seed, and renderer.

The paint layer is non-blocking, so wrapped buttons remain interactive during a celebration. fire() restarts the finite sequence, clear() stops it, and autoplay supports one-shot completion surfaces. One lazily allocated, fixed-capacity registry recycles particle slots and reusable motion buffers; the ticker stops when the sequence completes. Built-in stars use the same path-free canvas primitives as the edge and meteor effects.

Cinematic meteor transition #

With Navigator:

Navigator.of(context).push(
  TwinklePageRoute<void>(
    config: const TwinkleTransitionConfig.cinematic(
      direction: TwinkleTransitionDirection.left,
      sparkleDensity: 160,
      phases: [
        MeteorTransitionPhase(
          at: 0,
          starCount: 20,
          coverage: .22,
          gradientColor: Color(0xFFE6E0FF),
          gradientOpacity: .28,
          streakLength: .42,
          inversionStrength: 0,
        ),
        MeteorTransitionPhase(
          at: .5,
          starCount: 60,
          coverage: .6,
          gradientColor: Color(0xFF51477A),
          gradientOpacity: .68,
          streakLength: .23,
          inversionStrength: .12,
        ),
        MeteorTransitionPhase(
          at: 1,
          starCount: 160,
          coverage: 1,
          gradientColor: Color(0xFF080B23),
          gradientOpacity: 1,
          streakLength: .03,
          inversionStrength: .68,
        ),
      ],
    ),
    builder: (_) => const DestinationPage(),
  ),
);

With a router that accepts a Flutter transitions builder:

transitionsBuilder: (context, animation, secondaryAnimation, child) {
  return TwinkleTransition(
    animation: animation,
    secondaryAnimation: secondaryAnimation,
    config: const TwinkleTransitionConfig(
      direction: TwinkleTransitionDirection.up,
    ),
    child: child,
  );
},

No router package is required. Directions select the left, right, up, or down edge from which the shower grows. Each immutable phase controls its timing, active star count, viewport coverage, sky color and opacity, streak length, and inversion. Duration, curves, seed, pool capacity, star styling, travel, twinkle speed, and the handoff point are also configurable. For the built-in movie-scene pacing use:

const TwinkleTransitionConfig.cinematic(
  direction: TwinkleTransitionDirection.left,
)

The defaults start at 20 stars, grow through 60, and culminate at the bounded pool capacity in an opaque glittering night sky. The destination stays stationary and is revealed only at full coverage; the sky and color inversion then fade completely. The built-in curve starts gently and continuously accelerates into the climax. Returning does not rewind that movie: it runs a fresh accelerating shower from the opposite edge, covers the current screen, and reveals the previous screen underneath. One deterministic particle pool is allocated per transition configuration and reused for every frame. Built-in meteor stars use the same path-free primitive rendering as edge sparkles. TwinkleTransitionConfig.splash remains as a source-compatible alias for the cinematic preset.

Example and tests #

Run the gallery:

cd example
flutter run

Run all package tests:

flutter test

The public behavior scenarios live in test/features/visual_effects/visual_effects.feature and generate ordinary Flutter widget tests through bdd_widget_test.

Publishing #

Inspect and validate the exact pub.dev archive without uploading it:

dart pub publish --dry-run

The Pages workflow builds the example after package analysis and tests, using the base path reported by GitHub Pages. Before its first run, select GitHub Actions as the source under Settings → Pages. Pushes to main that affect the package or example deploy automatically; the workflow can also be dispatched manually.

Actual pub.dev publication remains an explicit interactive action:

dart pub publish
0
likes
160
points
--
downloads

Documentation

API reference

Publisher

verified publisherapplewood.sarl

Weekly Downloads

Composable sparkle, glitter, fireworks, and cinematic transition effects for Flutter.

Homepage
Repository (GitHub)
View/report issues

Topics

#animation #effects #fireworks #glitter #transition

License

MIT (license)

Dependencies

flutter, flutter_bloc

More

Packages that depend on twinkle_twinkle