2014-02-22 11:36:34 +00:00
|
|
|
|
(ns reagentdemo.news.clockpost
|
2015-07-31 07:58:07 +00:00
|
|
|
|
(:require [reagent.core :as r]
|
2014-02-26 12:17:18 +00:00
|
|
|
|
[reagent.debug :refer-macros [dbg]]
|
2015-02-09 20:02:31 +00:00
|
|
|
|
[reagentdemo.syntax :as s]
|
2015-09-08 18:18:27 +00:00
|
|
|
|
[sitetools.core :as tools :refer [link]]
|
2014-02-22 11:36:34 +00:00
|
|
|
|
[reagentdemo.common :as common :refer [demo-component]]
|
|
|
|
|
[reagentdemo.news.binaryclock :as binaryclock]))
|
|
|
|
|
|
2015-09-08 18:18:27 +00:00
|
|
|
|
(def url "/news/binary-clock.html")
|
2014-11-29 18:51:45 +00:00
|
|
|
|
(def title "A binary clock")
|
2014-11-29 17:30:24 +00:00
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
(defn fn-src [src]
|
|
|
|
|
[demo-component {:src src :no-heading true}])
|
2014-02-22 11:36:34 +00:00
|
|
|
|
|
|
|
|
|
(defn main [{:keys [summary]}]
|
2014-11-29 18:51:45 +00:00
|
|
|
|
(let [lexclock {:href "http://www.lexicallyscoped.com/2014/01/23/clojurescript-react-om-binary-clock.html"}
|
2014-02-26 12:17:18 +00:00
|
|
|
|
hopclock {:href "http://pmbauer.github.io/2014/01/27/hoplon-binary-clock/"}
|
|
|
|
|
om {:href "https://github.com/swannodette/om"}
|
2014-02-26 13:17:02 +00:00
|
|
|
|
hoplon {:href "http://hoplon.io"}
|
2014-11-06 19:21:38 +00:00
|
|
|
|
clocksrc {:href "https://github.com/reagent-project/reagent/blob/master/demo/reagentdemo/news/binaryclock.cljs"}]
|
2014-04-01 17:50:28 +00:00
|
|
|
|
|
2014-02-22 11:36:34 +00:00
|
|
|
|
[:div.reagent-demo
|
2015-09-08 18:18:27 +00:00
|
|
|
|
[:h1 [link {:href url} title]]
|
2017-11-28 17:16:26 +00:00
|
|
|
|
[:span "2014-02-26"]
|
2014-02-22 11:36:34 +00:00
|
|
|
|
[:div.demo-text
|
|
|
|
|
|
2014-02-22 16:24:22 +00:00
|
|
|
|
(when-not summary
|
|
|
|
|
[:div
|
2014-02-26 12:17:18 +00:00
|
|
|
|
[:div.clearfix
|
|
|
|
|
[binaryclock/main]]
|
|
|
|
|
[:div [:strong "Click to toggle 1/100th seconds."]]])
|
2014-02-22 11:36:34 +00:00
|
|
|
|
|
2014-02-26 12:17:18 +00:00
|
|
|
|
[:p "Fredrik Dyrkell wrote a very nice " [:a lexclock "binary
|
|
|
|
|
clock"] " using " [:a om "Om"] ". I thought I’d replicate that
|
2014-12-07 20:07:32 +00:00
|
|
|
|
using Reagent for fun (another re-write, using "
|
|
|
|
|
[:a hoplon "Hoplon"] ", can be seen " [:a hopclock "here"] ")."]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
2014-02-26 12:17:18 +00:00
|
|
|
|
[:p "So, without further ado, here is a binary clock using Reagent."]
|
2014-04-01 17:50:28 +00:00
|
|
|
|
|
2014-02-22 11:36:34 +00:00
|
|
|
|
(if summary
|
2015-09-08 18:18:27 +00:00
|
|
|
|
[link {:href url :class 'news-read-mode} "Read more"]
|
2014-02-22 11:36:34 +00:00
|
|
|
|
[:div.demo-text
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/syntaxed "(ns example
|
2015-07-31 07:58:07 +00:00
|
|
|
|
(:require [reagent.core :as r]))")]
|
2014-02-26 12:17:18 +00:00
|
|
|
|
|
2014-02-22 16:24:22 +00:00
|
|
|
|
[:p "We start with the basics: The clock is built out of
|
2014-02-26 12:17:18 +00:00
|
|
|
|
cells, with a light colour if the bit the cell corresponds to
|
2014-02-22 16:24:22 +00:00
|
|
|
|
is set."]
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:cell]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
|
|
|
|
[:p "Cells are combined into columns of four bits, with a
|
|
|
|
|
decimal digit at the bottom."]
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:column]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
|
|
|
|
[:p "Columns are in turn combined into pairs:"]
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:column-pair]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
|
|
|
|
[:p "We'll also need the legend on the left side:"]
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:legend]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
|
|
|
|
[:p "We combine these element into a component that shows the
|
|
|
|
|
legend, hours, minutes and seconds; and optionally 1/100
|
|
|
|
|
seconds. It also responds to clicks."]
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:clock]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
|
|
|
|
[:p "We also need to keep track of the time, and of the
|
|
|
|
|
detail shown, in a Reagent atom. And a function to update the
|
|
|
|
|
time."]
|
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:clock-state :update-time]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-22 16:24:22 +00:00
|
|
|
|
|
2014-02-26 12:17:18 +00:00
|
|
|
|
[:p "And finally we use the " [:code "clock"] " component.
|
|
|
|
|
The current time is scheduled to be updated, after a suitable
|
|
|
|
|
delay, every time the main component is rendered ("
|
2014-12-07 18:26:20 +00:00
|
|
|
|
[:code "reagent.core/next-tick"] " is just a front for "
|
|
|
|
|
[:code "requestAnimationFrame"] "):"]
|
2014-02-26 12:17:18 +00:00
|
|
|
|
|
2014-12-07 15:38:56 +00:00
|
|
|
|
[fn-src (s/src-of [:main]
|
2014-12-07 18:26:20 +00:00
|
|
|
|
"reagentdemo/news/binaryclock.cljs")]
|
2014-02-26 12:17:18 +00:00
|
|
|
|
|
2014-12-07 20:07:32 +00:00
|
|
|
|
[:p "The entire source is also available "
|
|
|
|
|
[:a clocksrc "here"] "."]
|
2014-02-26 13:17:02 +00:00
|
|
|
|
|
2014-02-26 12:17:18 +00:00
|
|
|
|
[:h2 "How it all works"]
|
|
|
|
|
|
|
|
|
|
[:p "Reading through the source, it may look like the entire
|
|
|
|
|
clock component is recreated from scratch whenever the time
|
|
|
|
|
changes. "]
|
|
|
|
|
|
|
|
|
|
[:p "That is an illusion: Reagent and React together
|
|
|
|
|
makes sure that only the parts of the DOM that actually need
|
|
|
|
|
to change are updated. For example, the "
|
|
|
|
|
[:code "column-pair"] " function corresponding to hours only
|
|
|
|
|
runs once every hour."]
|
|
|
|
|
|
|
|
|
|
[:p "And that’s what makes Reagent and React fast. Try
|
|
|
|
|
clicking on the clock to toggle the display of 1/100th
|
|
|
|
|
seconds. Most browsers should have no trouble at all keeping
|
|
|
|
|
up (even if they won’t actually show every 1/100th second:
|
|
|
|
|
they are typically limited to roughly 60 fps)."]
|
|
|
|
|
|
|
|
|
|
[:p "But it is a very handy illusion. Almost the entire UI is
|
|
|
|
|
made up of pure functions, transforming immutable data into
|
|
|
|
|
other immutable data structures. That makes them easy to
|
|
|
|
|
reason about, and trivial to test. You don’t have to care
|
|
|
|
|
about ”model objects”, or about how to update the DOM
|
|
|
|
|
efficiently. "]
|
|
|
|
|
|
|
|
|
|
[:p "Just pass arguments to component functions, return a UI
|
|
|
|
|
description that corresponds to those arguments, and leave it
|
|
|
|
|
to React to actually display that UI."]])]]))
|
2014-02-22 11:36:34 +00:00
|
|
|
|
|
2015-09-08 18:18:27 +00:00
|
|
|
|
(tools/register-page url [#'main] title)
|