strokes fork and port of mike’s general update pattern tutorial, II.
merge requests should go to the example in the repo
By adding a key to the data-join, letters that are already displayed are put in the update selection. Now updates can occur anywhere in the array, depending on the overlap between the old letters and the new letters. The text content only needs updating on enter because the mapping from letter to element never changes; however, the x-position of the text element must now be recomputed on update as well as enter.
It’ll be easier to see what’s going on when we add animated transitions next!
Next: Update Transitions
Previous: General Update Pattern
<!DOCTYPE html>
<meta charset="utf-8">
<style>
text {
font: bold 48px monospace;
}
.enter {
fill: green;
}
.update {
fill: #bbb;
}
</style>
<body>
<script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="gup2.js"></script>
</body>
(ns gup2
(:require [strokes :refer [d3]]))
(strokes/bootstrap)
; 26 characters in a vec
(def alphabet (vec "abcdefghijklmnopqrstuwvxyz"))
(def width 960)
(def height 500)
(def svg (-> d3 (.select "body") (.append "svg")
(.attr {:width width :height height})
(.append "g")
(.attr {:transform (str "translate(32," (/ height 2) ")")})))
(defn update [data]
; DATA JOIN
; Join new data with old elements, if any.
(let [text (-> svg (.selectAll "text") (.data data identity))]
; UPDATE
; Update old elements as needed
(-> text (.attr {:class "update"}))
; ENTER
; Create new elments as needed
(-> text (.enter) (.append "text")
(.attr {:class "enter"
:dy ".35em"})
(.text identity))
; ENTER + UPDATE
; Appending to the enter selection expands the update selection to include
; entering elements; so, operations on the update selection after appending to
; the enter selection will apply to both entering and updating nodes.
(-> text (.attr {:x #(* %2 32)}))
; EXIT
; Remove old elements as needed.
(-> text (.exit) (.remove))))
; The initial display - all letters
(update alphabet)
; Grab a random sample of letters from the alphabet, in alphabetical order.
(.setInterval js/window (fn []
(-> alphabet
shuffle
(subvec (rand-int 26))
sort
vec
update))
; 2 seconds between swaps
2000)