Skip to content

Instantly share code, notes, and snippets.

@mkhoeini
Created November 29, 2015 04:55
Show Gist options
  • Save mkhoeini/9231f8e6b8273944a5ae to your computer and use it in GitHub Desktop.
Save mkhoeini/9231f8e6b8273944a5ae to your computer and use it in GitHub Desktop.
Neet idea about tweening using reagent/reaction
; eurleif
;to Reagent-Project
;Nov 28
;I'm a newbie to Reagent, and I've just been playing around with it. I found a hack/pattern that seems pretty powerful. I'm curious if this is known/documented anywhere, and if there are problems with it that I haven't found. Any thoughts are appreciated.
;It starts with a "clock" reaction, which produces the current millisecond time:
(defonce clock
(let [callback-added? (reagent.ratom/atom false)
callback #(reset! callback-added? false)]
(reagent.ratom/reaction
(when-not @callback-added?
(reset! callback-added? true)
(reagent/next-tick callback))
(.now js/Date))))
;If you just put this in a div, [:div @clock], the millisecond time shows up. This is sort of similar to the clock demo on the Reagent homepage, which uses setInterval to update the clock; but this version updates on every animation frame, and only continues updating while it continues to be used. In other words, the clock won't keep updating if you unmount the div from the page.
;You can use the clock to build tweening:
(defn tween [tween-time start-value end-value]
(let [start-time (.now js/Date)
done? (reagent/atom false)]
(reagent.ratom/reaction
(if @done?
end-value
(let [elapsed (- @clock start-time)]
(if (> elapsed tween-time)
(do (reset! done? true) end-value)
(+ start-value (* (/ elapsed tween-time) (- end-value start-value)))))))))
;This definition is slightly non-trivial, because for performance's sake, it needs to stop referencing the clock reaction after the tween ends. If it didn't, code would have to run on every frame as long as the tween was still used on the page, even after it ended.
;Here's a component that uses tweening to fade in:
(defn fadein []
(let [opacity (tween 5000 0 1)]
(fn []
[:div {:style {:text-align "center"
:font-size "8em"
:opacity @opacity}}
"Hello world!"])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment