slosh

Baked 2D liquid animations for Flutter: waves, sticky wall droplets, and split/merge effects, with independent pool and droplet colors.

Bake once with sloshgen, then interpolate and paint with slosh. The player performs no runtime fluid simulation.

Install

flutter pub add slosh

Requires Flutter 3.38 or later and Dart 3.10 or later.

Load and play

Generate water.slosh.json with sloshgen, place it in your Flutter application's assets/ directory, and declare it in your app's pubspec.yaml:

flutter:
  assets:
    - assets/water.slosh.json

Load and decode once outside build, then reuse the asset:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:slosh/slosh.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final asset = SloshAsset.decode(
    await rootBundle.loadString('assets/water.slosh.json'),
  );
  runApp(MaterialApp(
    home: Scaffold(body: Center(
      child: Slosh(asset: asset, size: 160, repeat: asset.loopSafe),
    )),
  ));
}

The standalone example includes baked data and needs no asset bundle configuration. In the repository, run it with cd packages/slosh/example && flutter run -t slosh_example.dart.

Colors and playback controls

For a v2 asset authored with water and spray style IDs:

Slosh(
  asset: asset,
  styleColors: {'water': Colors.blue, 'spray': Colors.amber},
  styleOpacities: {'spray': 0.9},
)

colors and opacities provide layer-level fallbacks. Runtime style overrides precede baked style colors, then layer overrides and baked layer colors.

Supply a SloshController(vsync: this, asset: asset) to use play(), pause(), seek(seconds) and rate (positive, at most 100). The standalone example shows ownership and disposal. An omitted controller is owned by the widget. A supplied controller must use the same asset and be disposed by its owner after detachment. Only loop-safe assets can repeat; one-shot playback holds its final frame.

SloshPainter exposes the same renderer for a separate animation clock. Geometry and appearance support direct and reverse seeks without event replay.

Scope and cost

Supports v1 surfaces and v2 contours with synchronized vessel rotation, translation and clipping. Changing size, colors or playback speed needs no bake. Changing fill, friction, adhesion or the motion trail requires regeneration. Arbitrary parent transforms and live gestures do not recalculate the liquid.

The player uses bounded lookup, interpolation and painting. Assets may be shared between icons; loading/validation, decoded memory and drawing still have a cost. This is a stylized 2D effect, not a 3D or physically calibrated fluid simulator.

The larger repository playground and branded fixtures are excluded from the published archive. See the format guide and measured validation.

Libraries

slosh
Lightweight Flutter playback for baked 2D liquid animations.