forked from jtr13/d3book
-
Notifications
You must be signed in to change notification settings - Fork 0
/
update.Rmd
283 lines (192 loc) · 6.61 KB
/
update.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# Update, Enter, and Exit <i class="fa fa-refresh"></i>
## Lecture slides <i class="fa fa-television"></i>
[D3 Data Bind](https://github.com/jtr13/D3/blob/master/UpdateEnterExit.pdf){target="_blank"}
## Remove some elements <i class="far fa-minus-square"></i>
*a.k.a. more DOM elements than data values*
We'll start with six circles and remove some.
Download and open a fresh copy of [six_blue_circles.html](https://raw.githubusercontent.com/jtr13/d3book/master/code/six_blue_circles.html){target="_blank"} in Chrome.
Let's bind four data values to the six circles:
``` js
var svg = d3.select("svg");
svg.selectAll("circle")
.data([123, 52, 232, 90]);
```
Click the black triangle to view the `_enter`, `_exit`, and `_groups` fields.
We can store the selection in a variable:
``` js
var circ = svg.selectAll("circle")
.data([123, 52, 232, 90]);
```
Let's look at the exit selection:
``` js
circ.exit();
```
Try this:
``` js
circ.attr("fill", "red");
```
What happened and why?
Now try this:
``` js
circ.exit().attr("fill", "purple");
```
What happened and why?
What do you think this will do? Try it.
``` js
circ.exit().transition().duration(2000).remove();
```
Create a new variable `circ2` and compare it to `circ`:
``` js
var circ2 = d3.selectAll("circle");
circ.data();
circ2.data();
circ.exit();
circ2.exit();
```
What's going on?
## Add some elements <i class="far fa-plus-square"></i>
*a.k.a. more data values than DOM elements*
We'll start with six circles and add some.
Let's bind new data to the circles:
``` js
var circ = svg.selectAll("circle")
.data([123, 52, 232, 90, 34, 12, 189, 110]);
```
And look at the enter selection:
``` js
circ.enter();
```
How many placeholders are in the enter selection?
Let's add circles for each of these placeholders:
``` js
circ.enter()
.append("circle")
.attr("cx", "100")
.attr("cy", (d, i) => i * 50 + 25)
.attr("r", "20")
.attr("fill", "blue");
```
Try this:
``` js
circ.transition()
.duration(3000)
.attr("cx", "400");
```
What do you need to do to act on *all* of the circles?
``` js
svg.selectAll("circle")
.transition()
.duration(2000)
.attr("cy", (d, i) => (i * 50) + 25)
.attr("cx", "200");
```
## Data / enter / append <i class="fa fa-table"></i>
We'll start with nothing--not even an SVG--and add elements with the data / enter / append sequence.
Download and open a fresh copy of [d3template.html](https://raw.githubusercontent.com/jtr13/d3book/master/code/d3template.html){target="_blank"} in Chrome.
Let's first add an SVG and store it in a variable:
``` js
var svg = d3.select("body")
.append("svg")
.attr("width", "500")
.attr("height", "400");
```
Create an array of values:
``` js
var specialdata = [100, 250, 300];
```
Add rectangles:
``` js
var bars = svg.selectAll("rect")
.data(specialdata)
.enter()
.append("rect")
.attr("x", d => d)
.attr("y", d => d)
.attr("width", "50")
.attr("height", "30")
.attr("fill", "red");
```
## Exercise <i class="fas fa-dumbbell"></i>: horizontal bar chart
1. Create a new html file (try to recreate the template without looking... or save a copy of [this one](https://raw.githubusercontent.com/jtr13/d3book/master/code/d3template.html){target="_blank"}) and open it in your text editor.
> <i class="far fa-lightbulb"></i> *If you create a new file in RStudio, choose "Text File" and use the `.html` file extension when you save it. Do not choose "R HTML".*
Add a script that adds an svg element and horizontal bars of the lengths (in pixels) specified in `bardata`. Create the bars with the data / enter / append sequence.
``` js
var bardata = [300, 100, 150, 225, 75, 275];
```
## Merge selections <i class="fa fa-code-fork"></i>
a.k.a. combining update and enter selections with `.merge()`
Download and open a fresh copy of [six_blue_circles.html](https://raw.githubusercontent.com/jtr13/d3book/master/code/six_blue_circles.html){target="_blank"} in Chrome.
``` js
var svg = d3.select("svg");
var circ = svg.selectAll("circle");
var allcirc = circ.data([123, 52, 232, 90, 34, 12, 189, 110])
.enter() // 2 placeholders
.append("circle") // placeholders -> circles
.attr("cx", "100") // acts on enter selection only
.attr("cy", (d, i) => (i - 5) * 50)
.attr("r", "20")
.attr("fill", "red")
.merge(circ) // combines enter and update selections
allcirc.transition() // acts on all 8 circles
.duration(3000)
.attr("cx", "400")
.attr("fill", "purple");
allcirc.transition() // acts on all 8 circles
.duration(3000)
.attr("cx", "50");
```
## Exercise <i class="fas fa-dumbbell"></i>: merge
Open the bar chart you created in the previous exercise in Chrome, and work in the Console.
1. Change the data to any six other values and update the lengths of the bars.
1. Bind a new dataset, `newbardata` to the bars, update the bar lengths, and remove any extra bars.
`newbardata = [250, 125, 80, 100];`
1. Bind a new dataset, `reallynewbardata`, to the bars, then add additional bars so each data value has a bar. Make the outline (stroke) of the new bars a different color.
`reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275];`
1. Use `.merge()` to combine the update and enter selections into one selection and then transition the height of all of the bars to half their current height.
1. Add text labels inside the bars at the right end with the length of the bar in pixels.
## Groups <i class="fa fa-object-group"></i>
Download and open a fresh copy of [six_blue_circles.html](https://raw.githubusercontent.com/jtr13/d3book/master/code/six_blue_circles.html){target="_blank"} in Chrome.
Run this code in the Console:
``` js
var svg = d3.select("svg");
var specialdata = [100, 250, 300];
var bars = svg.selectAll("rect")
.data(specialdata)
.enter()
.append("rect")
.attr("x", d => d)
.attr("y", d => d)
.attr("width", "50")
.attr("height", "30")
.attr("fill", "red");
```
What's going on?
Refresh the page, and try the following instead:
``` js
var svg = d3.select("svg");
var specialdata = [100, 250, 300];
var bars = svg.append("g")
.attr("id", "rects")
.selectAll("rect")
.data(specialdata)
.enter()
.append("rect")
.attr("x", d => d)
.attr("y", d => d)
.attr("width", "50")
.attr("height", "30")
.attr("fill", "red");
```
Compare:
``` js
d3.select("svg")
.select("g#rects")
.selectAll("rect")
.attr("fill", "purple");
```
and
``` js
d3.select("svg")
.selectAll("rect")
.attr("fill", "purple");
```