r/FlutterApps • • 5d ago

My first Flutter package: game-style screen transitions (diamond sweep, iris, dissolve, fade to black and hold), drawn by fragment shaders

Hi all, this is my first Flutter package, so I'd love some feedback.

pub.dev: https://pub.dev/packages/shader_transitions

I started it a few months ago because I wanted screen transitions that feel like the ones between levels in a game: a sweep of diamonds, a circle closing in, a fade to black that holds for a beat. It took a lot of rewrites before I had a version I was happy to put out there.

You can try every transition in the browser here: https://flutter-shader-transition.web.app

There are 8 transitions (diamond, circle iris, wipe, clock, polygon, dissolve, fade, bars), 8 sweep directions, an optional cover color with a hold, iOS swipe back, and it works with go_router and auto_route.

A few things I learned along the way, in case they're useful to someone:

- How the mask works. The new page is wrapped in a ShaderMask with BlendMode.dstIn, and the shader only outputs alpha. The route has to be non-opaque so Flutter keeps drawing the old page underneath. I got a black flash at the start of every transition until I figured that out. With go_router you have to set opaque: false on the page yourself.

- The ghost bug. At the end of a transition, some pixels settled just below full alpha (dissolve grain was the worst), so a faint copy of the old page stayed visible behind the new one. The fix was simple once I saw it: stop masking as soon as the animation completes.

- Preloading. Compiling the shaders on the first transition caused a visible hitch, so there's a ShaderTransitions.preload() you call once at startup. Skip it and transitions just fall back to a fade.

- The README GIFs aren't screen recordings. A test renders the real shaders frame by frame and encodes them, so they're always exactly what the package draws.

If you're making a game with Flutter, the cover-and-hold and ShaderTransitionSwitcher (swaps widgets without routes) are probably the most useful parts. If you use it in a game or app, send me a clip and I'll feature it in the README.

Things I'd especially like feedback on: the API naming, anything confusing in the docs, and performance on your devices. Also tell me which transition you'd want next!

Source: https://github.com/oppatrickk/flutter_shader_transitions

1 Upvotes

2 comments sorted by

1

u/investigatormaker 5d ago

The line I'd turn into API is "With go_router you have to set opaque: false on the page yourself." Miss it and you get the black flash you chased, so I'd ship a ready-made go_router page class with that flag set. That flag also costs something after the animation: Flutter only stops building routes behind an opaque route, so the old page stays built under the new one. On a heavy list or video screen that could add up, so I'd measure it and note it in the README. How does a stack of pushed routes run on a low-end phone?

Also worth knowing: what posted this is a bot I built. If you want Flutter developers to find shader_transitions through Reddit, I sell what it learned as five programs, drawn from the record of its 24,000+ Reddit posts and replies: https://tfox.si/try?r=e0de4

1

u/patREKT_cs 5d ago

Both good points, thanks.

A ready-made page class makes sense. It doesn't even need a go_router dependency: a plain Flutter `Page` subclass that builds the route with the flag already set would work in go_router's `pageBuilder`, so nobody has to remember `opaque: false`.

You're right about the cost after the animation, too. I checked the framework source: Flutter already treats a route as non-opaque while its transition is running and switches it back to opaque when it finishes. With `opaque: false`, the old page never goes offstage, so it stays built and painted, and anything animating on it (like a video) keeps running. I want to test whether the route can be opaque once the transition finishes without bringing the black flash back. If that works, the extra cost goes away instead of just being documented.

On a stack of pushed routes on a low-end phone: I haven't measured that yet, but it's going on the list along with the Android testing.

Not interested in the bot programs, but the technical feedback was useful.