{"id":49055639,"url":"https://github.com/vyfor/animate","last_synced_at":"2026-04-21T00:01:28.034Z","repository":{"id":351434641,"uuid":"1210481465","full_name":"vyfor/animate","owner":"vyfor","description":"🎞️ Animation Library for Rust","archived":false,"fork":false,"pushed_at":"2026-04-15T12:14:00.000Z","size":1542,"stargazers_count":67,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-19T23:38:30.747Z","etag":null,"topics":["animate","animation","cli","framework","gui","interpolation","lerp","library","ratatui","rust","tui"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/animate","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vyfor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-14T13:09:23.000Z","updated_at":"2026-04-19T15:40:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vyfor/animate","commit_stats":null,"previous_names":["vyfor/animate"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vyfor/animate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vyfor%2Fanimate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vyfor%2Fanimate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vyfor%2Fanimate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vyfor%2Fanimate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vyfor","download_url":"https://codeload.github.com/vyfor/animate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vyfor%2Fanimate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32071013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T21:26:33.338Z","status":"ssl_error","status_checked_at":"2026-04-20T21:26:22.081Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animate","animation","cli","framework","gui","interpolation","lerp","library","ratatui","rust","tui"],"created_at":"2026-04-19T23:04:07.907Z","updated_at":"2026-04-21T00:01:28.022Z","avatar_url":"https://github.com/vyfor.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎞️ animate\n\nAnimation Library for Rust.\n\n![Demo](./.github/assets/demo.gif)\n\n## Features\n\n- **Lightweight**: Zero dependencies by default.\n- **Ergonomic**: Macro-driven API with minimal boilerplate.\n- **Extensible**: Many built-in types with support for custom interpolators.\n- **Animation modes**: `#[once]`, `#[cycle]`, and `#[alternate]`.\n- **Easing**: Built-in and custom easing functions.\n- **Ratatui-friendly**: Interpolators for ratatui types, gated behind the `ratatui` feature flag.\n\n## Installation\n\n```sh\ncargo add animate\n```\n\n## Getting started\n\nAdd `#[animate]` to a struct and mark the fields you want to animate:\n\n```rust\n#[animate]\npub struct MyWidget {\n    #[once(duration = 300)]\n    progress: f64,\n\n    #[cycle(duration = 400, easing = cubic_in)]\n    color: Color,\n\n    #[alternate(duration = 500, easing = quad_in_out)]\n    status: String,\n}\n```\n\nBy default the macro generates an update method named `animate`. It must be called at the top of your struct's render method.\n\n```rust\n#[animate]\npub struct MyWidget { ... }\n\nimpl MyWidget {\n    pub fn draw(\u0026mut self, frame: \u0026mut Frame) {\n        self.animate();\n\n        // rest of your code\n    }\n}\n```\n\nIf the name conflicts with an existing method, rename it:\n\n```rust\n#[animate(update = \"update_animations\")]\npub struct MyWidget { ... }\n```\n\nNext, place `animate::tick()` **before** your struct's update call at the start of each frame:\n\n```rust\nlet mut widget = MyWidget::new(...);\n\nloop {\n    animate::tick(tickrate);\n    terminal.draw(|frame| {\n        widget.draw(frame);\n    })?;\n}\n```\n\nUse `get()` to read and `set()` to write animated fields.\n\n## Minimal example\n\n```rust\nuse animate::animate;\nuse std::{io::{stdout, Write}, thread, time::Duration};\n\n#[animate]\nstruct Counter {\n    #[once(duration = 400)]\n    value: u32,\n}\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let mut c = Counter::new(0);\n\n    loop {\n        animate::tick(8);  // advance global frame time by frame delta (ms)\n        c.animate();       // update all animated fields\n\n        let v = *c.value;\n        if v == 0 {\n            c.value.set(100);\n        }\n\n        print!(\"\\rCounter value: {v}\");\n        stdout().flush()?;\n\n        if v == 100 {\n            break;\n        }\n\n        thread::sleep(Duration::from_millis(8));\n    }\n\n    Ok(())\n}\n```\n\n## Animation modes\n\n| Attribute      | Behaviour                                           |\n|----------------|-----------------------------------------------------|\n| `#[once]`      | Animates to target once, then holds.                |\n| `#[cycle]`     | Loops continuously from start to target.            |\n| `#[alternate]` | Ping-pongs back and forth between start and target. |\n\n## Fields\n\nAll mode attributes accept the same options:\n\n```rust\n#[once(duration = 300, easing = quad_in_out, interp = my_interp_fn)]\n```\n\n| Option     | Type       | Default             | Description                                      |\n|------------|------------|---------------------|--------------------------------------------------|\n| `duration` | `u64` (ms) | `0`                 | Animation duration in milliseconds.              |\n| `easing`   | path       | `linear`            | Easing function (`fn(f64) -\u003e f64`).              |\n| `interp`   | path       | `\u003cT as Lerp\u003e::lerp` | Interpolation function (`fn(\u0026T, \u0026T, f64) -\u003e T`). |\n\n## Built-in easing functions\n\n`linear`, `quad_in`, `quad_out`, `quad_in_out`,\n`cubic_in`, `cubic_out`, `cubic_in_out`\n\n## Custom types\n\nImplement `Lerp` for any type:\n\n```rust\nimpl animate::Lerp for MyColor {\n    fn lerp(start: \u0026Self, end: \u0026Self, t: f64) -\u003e Self {\n        MyColor {\n            r: u8::lerp(\u0026start.r, \u0026end.r, t),\n            g: u8::lerp(\u0026start.g, \u0026end.g, t),\n            b: u8::lerp(\u0026start.b, \u0026end.b, t),\n        }\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvyfor%2Fanimate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvyfor%2Fanimate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvyfor%2Fanimate/lists"}