Hacker News

Show HN: Inertia - Not your Grandfathers animation editor

A keyframe editor for the UI you already built Wrap the views you want to move, run your app inside the Inertia editor, and drag them around on a timeline. No exported video, no parallel design file - the thing you animate is the real view in your real app. macOS editor Β· iOS 17+ / minSdk 26 / React 18.3 Why Inertia Your app is the canvas Design tools export something that plays next to your UI rather than being it. Code-first libraries keep you in a compile-run-tweak loop where a 40 ms timing change costs a rebuild. Inertia sits between the two. Real components A real RoundedRectangle, a real Card composable, a real . No re-implementation and no design file that drifts from the app. Native playback SwiftUI plays tracks through KeyframeAnimator; Compose and React sample the same tracks on their own clocks. Nothing is rasterized. Live editing Your app connects to the editor over a local WebSocket, reports its tagged hierarchy, and receives updates as you edit. How it works Three steps, then it’s in your repo Tag a view Wrap anything you want to move with an id. That one call is the whole integration - shapes and tracks attach to the id. Drag it on a timeline Run the build inside the editor, select a tagged view, and move, rotate, scale, or fade it. The playhead is shared with the running app. Commit the file The editor writes an animation.inertia file. Designers scrub the timeline, developers git add the result - one file, three runtimes, identical ids. The editor Scrub against a build that’s actually running The centre panel is your app - installed and launched on the iOS Simulator, an Android emulator, or your dev server in a WebView. Select a tagged view, drag it, and the keyframe lands on the timeline. Runtimes One API, three platforms Every runtime has the same three pieces: a container that owns the animation data, an actionable wrapping each view you want to move, and a playback handle for starting it. - trigger starts a track; one arriving mid-run joins the run in progress. - restart rewinds - every actionable in a container is drawn from one clock. - cancel returns an animation to its initial values and leaves it there. - isRepeating switches looping and play-once at runtime. import SwiftUI import Inertia InertiaContainer(dev: isEditor, id: "animation") { ContentView() } struct ContentView: View { @Environment(.inertiaDataModel) private var inertia: InertiaDataModel! var body: some View { VStack(spacing: 16) { Card(title: "Welcome") .inertia("card0") // tag the view you want to move Button("Trigger") { inertia.restart("card0") } } } } | Runtime | Package | Editor target | Shapes | |---|---|---|---| | SwiftUI | Inertia (SPM) | iOS Simulator, driven through simctl | Metal | | Jetpack Compose | inertia-compose (JitPack) | Android emulator, over adb | OpenGL ES 2.0 | | React | inertia-react + inertia-base | Your dev server, in a WKWebView | WebGL | The handoff One .inertia file The editor writes an animation.inertia file into a project folder you version alongside your source - one record per tagged id, each a pose plus the track that leaves it. - translate - an [x, y] offset as a fraction of the container, so a track survives a resize. - scale, opacity - uniform factor, and 0 through 1. - rotate / rotateCenter - degrees, anchored top-left or at the view’s centre. - invokeType - auto starts when the view appears; trigger waits for your call. { "id": "card0", "initialValues": { "opacity": 1, "rotate": 0, "scale": 1, "translate": [0, 0] }, "invokeType": "trigger", "keyframes": [ { "duration": 0.001, "values": { "scale": 0, "translate": [-0.008, -0.269] } }, { "duration": 2.011, "values": { "rotate": 90, "scale": 1, "translate": [-0.013, 0.278] } } ], "shapes": [] } Also in the box Details that make it usable Alignment guides Drag a view and it snaps against its neighbours, on SwiftUI and Compose alike. Vertex shapes Author geometry behind a view - rectangles, ovals, triangles, or raw vertices with per-corner colour. No shape API to call. Shared playhead Pause, resume, seek and loop length are shared both ways, so the timeline tracks a running animation. Editor mode is opt-in In release, none of the socket code runs. The container loads the animation and plays it on its own clock. Per-view state Two views can share one animation id and keep their own playback state - trigger one without touching the other. Versioned with your app One .inertia project folder per app, sitting in the repo next to the code it animates. Get started Get a view moving in a few minutes Add the package, tag a view, and open the editor. The quickstart walks all three runtimes end to end. Download Get the macOS editor Leave an email and the build is yours - the editor, the three runtimes, and the sample project the quickstart uses.

Read on Hacker News ↗ ← Back to News

Comments

No comments yet. Start the discussion.