12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ClojureAdvent Calendar 2017

Day 2

reanimatedでreagentのUIを楽しくする

Last updated at Posted at 2017-12-01

tl;dr

  • reagentは理解できるけど、cssのtransitionとかは厳しい、でもUIには動きを付けたい筆者のような人にオススメのreanimatedというライブラリがある
  • 勉強兼ねてデモ作ってみた。ソース

デモGIF

demo.gif

##デモのコード

(ns reanimated.demo
  (:require [reagent.core :as r]
            [reanimated.core :as rc]))

(defn item [s stuff]
  (let [size (r/atom 40)
        spr (rc/spring size)]
    (fn []
      [:div {:on-click #(swap! stuff
                               (fn [stuff]
                                 (assoc stuff s false)))
             :style {:font-size (str @spr "px")
                     :margin "10px"
                     :cursor "pointer"}}
       s
       [rc/timeline
        #(reset! size 100)
        200
        #(reset! size 40)]
       (when-not (get @stuff s)
         [rc/timeline
          #(reset! size 100)
          400
          #(reset! size 20)
          200
          #(swap! stuff dissoc s)
          ])])))


(defn main []
  (let [size (r/atom 40)
        tl (r/atom false)
        spr (rc/spring size
                       {:from 9
                        :velocity .8
                        :mass 2
                        :stiffness 0.13
                        :damping .17})
        stuff (r/atom {"foo" true
                       "bar" true
                       "baz" true})]
    (fn []
      [:div
       [:span {:on-click #(swap! tl not)
               :style {:font-size (str @spr "px")}}
        "click me!"
        (when @tl
          [rc/timeline
           #(reset! size 100)
           200
           #(reset! size 40)
           #(reset! tl false)])]
       [:hr]
       [:div
        [:input {:type "button" :value  "Add stuff"
                 :on-click #(swap! stuff
                                   (fn [stuff]
                                     (assoc stuff (str (gensym "stuff")) true)))}]
        [:input {:type "button" :value  "Remove stuff"
                 :on-click #(swap! stuff
                                   (fn [stuff]
                                     (assoc stuff (ffirst stuff) false)))}]
        [:div {:style {:display "flex"
                       :flex-wrap "wrap"}}
         (->> @stuff
              sort
              (map (fn [[s]] ^{:key s} [item s stuff]))
              doall)]]])))

(r/render [main]
          (js/document.getElementById "app"))

インストールetc

執筆時点での最新→[reanimated "0.5.3"]
注意点として、react-with-addonsに依存しており、
[cljsjs/react-with-addons "15.6.1-0"]
を依存に加える必要があるが、そうすると:advancedモードでビルドする際にreactのduplicate extern的なエラーが出てビルドが出来ない。

reactが重複している事が原因なので[reagent "0.7.0" :exclusions [cljsjs/react]]の様にreagentのreactを除外する必要がある。 参考

追記:

react-with-addonsへの依存を消すプルリク送ったのがマージされてリリースされているので最新版では解消されている。

主な関数

具体的な使い方は本家のdevcardsが充実しているのでそちらを見る方が良いが、特に良いと思った物を2つ紹介する

reanimated.core/spring

  • reagentのatomを引数に取り、reagentのreactionを返す
  • 引数のatomの内部の数値が変更された際に、バネっぽくびよーんとした感じの数値を時系列にreactionに反映する
  • パラメーターでバネの動きを好みに調整することができる

reanimated.core/timeline

  • reagentコンポーネントとして、副作用を定義できる
  • コンポーネントが最初に描画された際の動きをつけることや、ボタンのクリック等に対する動きを書きやすい

感想

  • cssのtransitionとか過去に何回か理解しようとして挫折したので、どうしても自力でアニメーションをつける必要がある時はこのライブラリを使おうと思った
  • コンポーネントに副作用を含める事はアンチパターンとして認識していたが、アニメーションを目的にするのであれば理に叶っているのでは、と思った

宣伝

  • 12/12日にclj-nakanoでSituatedプログラム・チャレンジのClojureを担当しますので是非参加をご検討下さい
  • 現在フリーランスClojuristとして仕事をしております。Clojurist月(人月のClojurist版)が足りない等ございましたらお声かけいただければ。

今年は特に首都圏でClojure大盛り上がりでしたね!
Clojureを使う企業も今後増えていくと思われるので、どんどん普及していくと楽しいなーと思っています。

では皆様良いお年を〜

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?