1- Very much still a WIP. API is mostly final and this can create animations. Just missing large amounts of features to make this useful in any real project.
1+ # COSMIC TIME
2+ ## An animation toolkit for Iced-rs/Iced
23
3- TODOs before release:
4+ > This Project was build for [ Cosmic DE] ( https://github.com/pop-os/cosmic-epoch ) . Though this will work for any project that depends on [ Iced] ( https://github.com/iced-rs/iced ) .
5+
6+
7+ The goal of this project is to provide a simple API to build and show
8+ complex animations efficiently in applications built with Iced-rs/Iced.
9+
10+ ## Project Goals:
11+ * Full compatibility with Iced and The Elm Architecture.
12+ * Ease of use.
13+ * No math required for any animation.
14+ * No heap allocations in render loop.
15+ * Provide additional animatable widgets.
16+ * Custom widget support (create your own!).
17+
18+ ## Overview
19+ To wire cosmic-time into Iced there are five steps to do.
20+
21+ 1 . Create a [ ` Timeline ` ] This is the type that controls the animations.
22+ ``` rust
23+ struct Counter {
24+ timeline : Timeline
25+ }
26+
27+ // ~ SNIP
28+
29+ impl Application for Counter {
30+ // ~ SNIP
31+ fn new (_flags : ()) -> (Self , Command <Message >) {
32+ (Self { timeline : Timeline :: new ()}, Command :: none ())
33+ }
34+ }
35+ ```
36+ 2 . Add at least one animation to your timeline. This can be done in your
37+ Application's ` new() ` or ` update() ` , or both!
38+ ``` rust
39+ static CONTAINER : Lazy <id :: Container > = Lazy :: new (id :: Container :: unique );
40+
41+ let animation = chain! [
42+ CONTAINER ,
43+ container (Duration :: ZERO ). width (10 ),
44+ container (Duration :: from_secs (10 )). width (100 )
45+ ];
46+ self . timeline. set_chain (animation ). start ();
47+
48+ ```
49+ There are some different things here!
50+ > static CONTAINER: Lazy< id::Container > = Lazy::new(id::Container::unique);
51+
52+ Cosmic Time refers to each animation with an Id. We export our own, but they are
53+ Identical to the widget Id's Iced uses for widget operations.
54+ Each animatable widget needs an Id. And each Id can only refer to one animation.
55+
56+ > let animation = chain![
57+
58+ Cosmic Time refers to animations as [ ` Chain ` ] s because of how we build then.
59+ Each [ ` Keyframe ` ] is linked together like a chain. The Cosmic Time API doesn't
60+ say "change your width from 10 to 100". We define each state we want the
61+ widget to have ` .width(10) ` at ` Duration::ZERO ` then ` .width(100) ` at
62+ ` Duration::from_secs(10) ` . Where the ` Duration ` is the time after the previous
63+ [ ` keyframe ` ] . This is why we call the animations chains. We cannot get to the
64+ next state without animating though all previous [ ` Keyframe ` ] s.
65+
66+ > self.timeline.set_chain(animation).start();
67+
68+ Then we need to add the animation to the [ ` Timeline ` ] . We call this ` .set_chain ` ,
69+ because there can only be one chain per Id.
70+ If we ` set_chain ` with a different animation with the same Id, the first one is
71+ replaced. This a actually a feature not a bug!
72+ As well you can set multiple animations at once:
73+ ` self.timeline.set_chain(animation1).set_chain(animation2).start() `
74+
75+ > .start()
76+
77+ This one function call is important enough that we should look at it specifically.
78+ Cosmic Time is atomic, given the animation state held in the [ ` Timeline ` ] at any
79+ given time the global animations will be the exact same. The value used to
80+ calculate any animation's interpolation is global. And we use ` .start() ` to
81+ sync them together.
82+ Say you have two 5 seconds animations running at the same time. They should end
83+ at the same time right? That all depends on when the widget thinks it's animation
84+ should start. ` .start() ` tells all pending animations to start at the moment that
85+ ` .start() ` is called. This guarantees they stay in sync.
86+ IMPORTANT! Be sure to only call ` .start() ` once per call to ` update() ` .
87+ The below is incorrect!
88+ ``` rust
89+ self . timeline. set_chain (animation1 ). start ();
90+ self . timeline. set_chain (animation2 ). start ();
91+ ```
92+ That code will compile, but will result in the animations not being in sync.
93+
94+ 3 . Add the Cosmic time Subscription
95+ ``` rust
96+ fn subscription (& self ) -> Subscription <Message > {
97+ self . timeline. as_subscription :: <Event >(). map (Message :: Tick )
98+ }
99+ ```
100+
101+ 4 . Map the subscription to update the timeline's state:
102+ ``` rust
103+ fn update (& mut self , message : Message ) -> Command <Message > {
104+ match message {
105+ Message :: Tick (now ) => self . timeline. now (now ),
106+ }
107+ }
108+ ```
109+ If you skip this step your animations will not progress!
110+
111+ 5 . Show the widget in your ` view() ` !
112+ ``` rust
113+ anim! (CONTIANER , & self . timeline, contents )
114+ ```
115+
116+ All done!
117+ There is a bit of wiring to get Cosmic Time working, but after that it's only
118+ a few lines to create rather complex animations!
119+ See the Pong example to see how a full game of pong can be implemented in
120+ only a few lines!
121+
122+ Done:
4123- [x] No heap allocations in animation render loop
5- - [x] Compile time type guarentee that animation id will match correct animation to correct widget type.
124+ - [x] Compile time type guarantee that animation id will match correct animation to correct widget type.
6125- [x] Animatable container widget
7126- [x] Looping animations
8127- [x] Animation easing
128+ - [x] test for easing
9129- [x] add space widget
10130- [x] add button widget
11131- [x] add row widget
@@ -14,16 +134,15 @@ TODOs before release:
14134- [x] Use iced 0.8
15135- [x] use iced 0.8's framerate subscription
16136- [x] Add logic for different animation Ease values
17- - [ ] Documentation
18- - [ ] Add ` Cosmic ` cargo feature for compatibility with both iced and System76's temporary fork.
137+ - [x] Documentation
19138- [x] optimize for ` as_subscription ` logic
20139- [x] Add pause for animations
21- - [ ] Lazy keyframes. (Keyframes that can use the position of a previous (active or not) animation to start another animation.)
140+ - [x ] Lazy keyframes. (Keyframes that can use the position of a previous (active or not) animation to start another animation.)
22141
23- Other TODOs:
24- - [x] test for easing
142+ TODOs:
143+ - [ ] Add ` Cosmic ` cargo feature for compatibility with both iced and System76's temporary fork.
144+ - [ ] Low motion accesability detection to disable animations.
25145- [ ] general animation logic tests
146+ - [ ] Work on web via wasm-unknown-unknown builds
26147- [ ] physics based animations
27- - [ ] Low motion accesability detection to disable animations.
28148- [ ] Figure out what else needs to be on this list
29- - [ ] Work on web via wasm-unknown-unknown builds
0 commit comments