From b3056b0f380e281c32e71d0bef50f5da83001cb3 Mon Sep 17 00:00:00 2001 From: jtr13 Date: Mon, 25 Nov 2024 20:30:45 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20jtr13/d3?= =?UTF-8?q?book@f954ba6cfab59c82ba09d1b4fe048d567142149a=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 2 +- appendix-advanced-css.html | 2 +- correlation-coefficient.html | 2 +- d3console.html | 2 +- general-advice.html | 2 +- index.html | 4 ++-- interactivity.html | 2 +- jump.html | 2 +- just-enough-js.html | 2 +- layouts.html | 2 +- line-charts.html | 2 +- object.html | 2 +- pdfs/object_constancy.pdf | Bin 163105 -> 156644 bytes population-density.html | 2 +- reading-files.html | 2 +- scales-and-axes.html | 2 +- search_index.json | 2 +- share-d3-online.html | 2 +- solutions.html | 2 +- spearman-rank-correlation-coefficient.html | 2 +- transitions.html | 2 +- update-enter-and-exit.html | 2 +- weather-forecast.html | 2 +- web.html | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/404.html b/404.html index fa029bf9..58a06e86 100644 --- a/404.html +++ b/404.html @@ -23,7 +23,7 @@ - + diff --git a/appendix-advanced-css.html b/appendix-advanced-css.html index bed6ab5f..ce607260 100644 --- a/appendix-advanced-css.html +++ b/appendix-advanced-css.html @@ -23,7 +23,7 @@ - + diff --git a/correlation-coefficient.html b/correlation-coefficient.html index d8ac9c8e..a0a79f1e 100644 --- a/correlation-coefficient.html +++ b/correlation-coefficient.html @@ -23,7 +23,7 @@ - + diff --git a/d3console.html b/d3console.html index 3c1d1661..b4a7d1fe 100644 --- a/d3console.html +++ b/d3console.html @@ -23,7 +23,7 @@ - + diff --git a/general-advice.html b/general-advice.html index 9036d472..b87b8b8d 100644 --- a/general-advice.html +++ b/general-advice.html @@ -23,7 +23,7 @@ - + diff --git a/index.html b/index.html index 084e0581..cdb32208 100644 --- a/index.html +++ b/index.html @@ -23,7 +23,7 @@ - + @@ -390,7 +390,7 @@

Welcome to D3

diff --git a/interactivity.html b/interactivity.html index b0ed9295..837f3e5f 100644 --- a/interactivity.html +++ b/interactivity.html @@ -23,7 +23,7 @@ - + diff --git a/jump.html b/jump.html index d33c1235..4f608f8d 100644 --- a/jump.html +++ b/jump.html @@ -23,7 +23,7 @@ - + diff --git a/just-enough-js.html b/just-enough-js.html index beced578..6197d8f7 100644 --- a/just-enough-js.html +++ b/just-enough-js.html @@ -23,7 +23,7 @@ - + diff --git a/layouts.html b/layouts.html index 201ee3ee..2ff98f2f 100644 --- a/layouts.html +++ b/layouts.html @@ -23,7 +23,7 @@ - + diff --git a/line-charts.html b/line-charts.html index 0f107e82..164fea3a 100644 --- a/line-charts.html +++ b/line-charts.html @@ -23,7 +23,7 @@ - + diff --git a/object.html b/object.html index 3d3e5e96..11ced0fe 100644 --- a/object.html +++ b/object.html @@ -23,7 +23,7 @@ - + diff --git a/pdfs/object_constancy.pdf b/pdfs/object_constancy.pdf index 76006ac0ae4aa36d38e0f30bb927dcd9698212f9..81d05489ee071d3068d644b8c06de3e69bfb4086 100644 GIT binary patch literal 156644 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

AYGpM^~*gP={se({K%y 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'vd|ql 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 z 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 Zue0iK(ZTr# zUQINU0_0i(Xzm!=BaB{5VZkQ%D0pM4@OWp+_jst9)7{dtvJxMd;7SV>tmE7-k*uh| zU6LR`_JO_=NPCG;-8zLCShfWAAwd~Xr};xnEDsV%hiKJvW2e;2NaO3ih@VgmAH`MK zVY7NJX1mjxn{6nGQ`UrYzsI!hSlbL4eeNB#WZRAM*P9;U8{nA*!1Dv`_l+?|ZAThc zqMQ}F?}@9xgeB9In&URxB>PsK`FiUwd@GIoF{_q1WKyjd-4fjr>pEFCStsY-8MkfB z7xlVupDoP~r+&g-XMGQYI>hEyJOH8t{{Hp^z6 zu!9FhshxP|<^>={jU~C_^dVQ!m65#~NNgj4tS2;p6x6z?gPoyvBBYl~6snw_KmIB> zff8sq%r_RKU(V1jPaHkBOR!gJQDm&B4Gtd(%2-i*)hpFG-Nm0-cSLT!NV4=@URwp+ z{JD*@+q$p4-M2{_X*Qqdyc$8wjxgR{;NYRPbO_GaUO;Xmrba|7{1uAJHO2+iVnsI^ zp1ie6C=GBOl2@!Nwh!pRFMtW-U)=dj>4pX`K0+bmw_#X_%r>#lGP-n;y5@VR>(pz=uDfXWc3W<{RgtszkDD<<_ zbqZ<(*|ws-7B_oDHR-pnk?NYs-|6>v6sPB}J~b!LGmH3U?wa@D5KE)TqVzjOgLpCy zN_?x4w(d0yBv622gYf9NV~h>T?43q>el^UAKi02K>k|SYLL`!lIdx+Vi}@yZ0!X^R zNJXs;ahWk-H|tp#YSmB4)B($9lw(lURi__iF_1^)Ur*3(K-NJ(-*wV?*Uj2|*4M8w z3#zOr_v@u?GCIgy7;<4cbh4aUyd~rthU3h_pp(`Q-pV4%Njo#Ha{*n8tTZE5N|k!J z@n3tmS>wh^>#k7Mvf5?tBo5OUrBl|QbIk%dmJJ612LwhQc1>xZVocThi-z%v-%h@J z^}Vzt%XC|-;;2dGGh1UdFcnF!#HaH+(>5Os>C0$52kt(u48Y*C7Lv*o@4%J3{PTCm7IJWQ>Bh$N;}9_R^Kuy7ZWQ*4ILHmV(}_7lf6d$OK;wo zHG|08XdvkIL=Gee*-InBF&l{u!BGkt0(*grXRR2ejA29-;$IQ?Kncw z`;LAxi$KSjIixiPSQNDKiJgeT2V~g@R&kRwA>4Ed2BP>hd_Ie2<5*nM29d(yC~(%K zfa_U&-Sqy(iJmgp3c&@3C)+59`C0Afs>9Z`L(iej^_V(4#t1ZQ-{7q~jbjBrYOeak z#0+~#95E1w&a8?SM!KkEW4W{LF%75|)_B}Rh2{+wrgq@EvJk7GW6?M=sK-7vXvpw# zDr7&J_Ug?*Jr+E;vphyE38;vzVJ~@yicto2CX-y^RS98E|Z-8R}ZV#EJy@SmH$4e%6=cL@Wx{OK9siLo+JNpdnUJz}90n`Y%*0uLrL2ux;Q zO21_RvSW=4dT?{9@r`lG+bOh+=jST}9PWxE;BdYm-)$S0$eCvN616`90&LMZ7noCk zJ44>^h(VkaZ7Jrc>5&0p=v{sacfpeJZaFZAC>Lqhc_)EY&jI+Ks%eVz`R7V~ZFe={6RuTE%L$KC!uS1&3`r4zDJ zKB|lsf2Fe~E7%<`2r8BMNUWd2P+pmcP=NcU2=DC>(pY`j zlU7J~Mu6926Kb7F>;QaY13v~*U1b5}YzP&l?LkPPvM|Ec@$QPg5Tida%8^rjZx9Ee z*rxP-h$xwnYoD=2%cDb|vCJGlUz?6jIZqaG(++n;QG;`K-bbiBJ`(~nVh3n=gEhP* zWL$@a$ub(E!Q|Bns9{U{c6f#nf6$=Ey6Og~@|fZn%gb`pPp)GyR``&bgl+LKxYIAP z7SeD=s%IP=gZ|b6*@{w+ZNnP<5te0k-MPmQ(fZv7v0mDYJ~(eWX2#~4TpfGQdOQf+knvoTtIH3EcZ( zUJcvPneBtbmme{bavFBh6~`$booAM}K*)!2-oaz3Bm8c?e$D{H4+)F)sr(BA7C!6gH!i!J$R z9z>y=#1^nPIGz)nT~?E6l&F@hw!b^pQl@S1&6C_Gb7{|#H^B0@1*LvCmj-Ns1!`ct z;9&_cfUNs}4~Pt~^2Z8T3rGR91y}=Z!l!_6!8*3hn-JI@*g+Lw%QML{%EQVN%X7;! z6~Oj)1H1r-0?G#ahJDO5`v?#XGzyl4gU8`d&yqIcKQZfcTgN2$IQ(!jFn+7H6MAF{ zUpa%RHjS$`jja~?bQk{t6`CCNwS^_`!hXcRio;OH;i!=*c4CjHb5-$JX*@3(9vm8) ze%9Sq86GSdnkp0!zE5!Z0_R)|oL*t5xYk1z&-F`PbC>|Jhhog3frQT+( z>h#v|JgB>+Qu@$O8Rp*qZ-i|B5cmAi^l~yXaQmwaeuXbu~fduF6{q+f&V3C`&0g}M__0BTja*Z@@Lq- z9#EVte(c`=_MsFQm#pLq)NE3BYKX{_tM@ z0exX)WB4BxZJg|1>cc-GI@7Oefdvy+rOzV zj0|5in189;SlGS*GJj)Vp#ETA{<_Y-f-7Don9dy*w58ECq7Qbtqs#Sia)#5ER3$*3;7UhdpUHU0D6Yy_I#FTC{ zBPrqf357hNsr3O+V<2c>!5XpyCgWGjL$vTz(X=P3Y)lg;6&R!qBJx8QfDFH{LK+$x z^w+^mkkxl?f9AfrPq_Iju+ri`y3g=F@_Z~m&-hJWfUDu@s0^JJG%T##G>%MDezd~x zonepQec;j-k-qU z9^>|y zn%$ng{$!=CEDHIHN-LsrFZc$gyFLC?HRN{BO>+;^#YN3l8FOEagOk=u>b^ovHFe5T z^pTyvI7czYYLJoym9;!wn<}z=VJc2n71CuWS3}v&kwv zSZL-{RU)|}aPTKW%z#xXmPoCTw{8Jn(R5jm6$Ebnt6oxU1(s?k`N>)s9{XN9j{Ll9 zxmCYMMG`*jY%{*`xp;aw)U_*S=+Btxr9HS!cms!vaWQMYZn}{!h#HsoQ%jfULvWes zW>noWA@wpK=!KO?slCzsvrcWUbD*(xHr9B*34o0jm)4yWxP+twt~-{{=5&EPON4?$ zu;Szr77y*3L%~Kzm*2tPMBcrci}1kT)#9}l#TPvH&qX1}RrC6vU~6x&Lr&i%=zdn_ z1TOHJzqqpgDzgxc*$eos@-*Cfn?YA}be$)ZY0LfPX1cXXk2O4UxD<^IUt2!5Mjfwn zcC340J#G;tQX(f;g9Y8nKv*bdjWTK#Wux1i@#8YL`G_b^6fcwSM#IE)A1#lzz&1c{0@#%^V2Q>Q8A((GmZdm znbBqaNZB-Sqnpe9>Ifb*f2bqJvUO-XtMTMmZ|@BR7+n#hNslrbpc72*{_4cQ{guoUbeS9HHM znykz&kOrubZ_JEsZRL=$JX8hgodWWAsgaX?y?O@k8Qc8>I;~hvH3Tj&erAQS+v7 zNT1@_c)O;dqBr7ppf5jC>mJl^bXt|c~OJa3#s87^#2L-Y4CXK=6Wrg-o z!t4#oa)y=e%%qdFs}zyYMqSng8MnWS2u!iMxF7cdOQLL>#n9cB-#(SN{5kmc^Q_Ba zQ=xIV;#k(nOQMcM+Um9*lbl&JXOFl}>m4z@VJFa}8n5M>W1rU@2!Zf8jCk5BkwQ z_264#jfD{Lq13x3c>6;YVJOkhtC1`tW&qn=)+8#5ywfWQ63MnPl_9bVkSgI&1~tKs zxq@VKfz$uY4K~>dTfgU8R!W78hlpnKhcHmV3=i0rW0y1A zdlsMe>)X)N`H9xXXZgn50&ul3879MmU0YqgH0=rz2CgzKT@?h1=Muo}0GVO#e_f4` z*p5Ee+aahqt`Lv87!i#USzw;>!T@+G9O17HN(0eKwnLK?4xJl1&QKOw&3GwHZQw`< znG7vfp^zNHPH(Qw1j|;J4&E&iUxQEpz7ycKD>AqQY7rSASDYxr z7nf4rouel6U3lN&bsyiE7CMXA3YjP$A|ZuaX|Ig8$V4_ofV{RW5WQjtRrOj3brkVI z2(?oIl>RsvN&&CBGyU9(Q7n2gJlQdL%T^d#NsIb+Q}Ji>oWc3_Qk`+pDn-?$g_Q+- zDh74@LSMb`N#yB|?)-d}N!!Vdn?94WM)xMtcnhcy?vV_zSbKX*-1XI2uGL(dm?15y zzSD0j*+`=rYfryjA-;o85C06O1P2(ey^{}(*Leqn$IdT zARG@476o(}ism@2ha~yUn;y&fnnz-=g$wdHBRfml$r|Q;pNSrtf>a;`okScm9OBr7 zIEV?|$zKKHdp&B-2O$YszbHV>yWClR--XV?zFs3ydGT`^{Ua|;_qUhnQ zO^KjjYbpRe^mrSMio{{xeX0_53=%(0{sx=N)eI|akJPL_w!6C~y4uyt8jRRr@Fm(0(Zk=%^J%9Ne{T-B!->atnM!|N zO3Zi!-AEQvETCClRa;4hD7#0qs=3;nNnBAfN5#pxU5zcQ8vjnOPru1eF`?MbYpa0z zMD4TF8n@2U6Tf0#CDIU6%EM$b0HKTEY#S`pQ6^Z<5{^8rE|m=NV4-T9Km72l{3K z&ngR_00a=v`e=ZFXRE7Mpo6tk=05>*#{%|n(xDBi&=fTBi3(WpSSxYI+FJ(+Gh4@+ zN4D6ieIfQ))@YtUV`ayFhRq2J$Zb(tXi0n^pZ&`HyJseM^@+RiVv^_l+syE|IiGXx z%}I!{>rL6v+ee0!!6m^(wF&PJ|50s0;r&Kff(wC$GI)Hz9XRE;U@zBH|5O$S zK|R!Ac+9*U-MkId*%PK-<|OGwg0;e2IOr!Xz;8Q6V0QPA{xd`gse?h@8m$eYz0^i# zI+Nr)yrs@%$b%r#?t8>v-+p+gr&usL8D_L3_=7U-5ej$EURmWe9|8d=1L%1`lFLC$ z#C}e&JY12&;1X5ZUVtM(alCQQdf_OCIL;%0AnLT?tX0OqRmOs9UqS(ha?tXx=@atH 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

@@(pMR3Xl^H^4BTp;Ej9<I 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 V&cF6Pfu4a}3hlvz3aW~<{}1$HSY7}C diff --git a/population-density.html b/population-density.html index 8f172df9..4b1f7573 100644 --- a/population-density.html +++ b/population-density.html @@ -23,7 +23,7 @@ - + diff --git a/reading-files.html b/reading-files.html index ebb6f0d9..f6dad933 100644 --- a/reading-files.html +++ b/reading-files.html @@ -23,7 +23,7 @@ - + diff --git a/scales-and-axes.html b/scales-and-axes.html index a0f00bd6..d72d2529 100644 --- a/scales-and-axes.html +++ b/scales-and-axes.html @@ -23,7 +23,7 @@ - + diff --git a/search_index.json b/search_index.json index 8f784368..9606ae02 100644 --- a/search_index.json +++ b/search_index.json @@ -1 +1 @@ -[["index.html", "D3 for R Users Welcome to D3 0.1 Workflow", " D3 for R Users Joyce Robbins 2024-11-21 Welcome to D3 rect { pointer-events: all; } .node { fill: blue; } .cursor { fill: none; stroke: brown; pointer-events: none; } .link { stroke: red; } .svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 20%; vertical-align: top; overflow: hidden; } .svg-content { display: inline-block; position: absolute; top: 0; left: 0; } Adapted from Build Your Own Graph! This guide serves as a companion text to Scott Murray’s Interactive Data Visualization for the Web, 2nd edition–henceforth IDVW2–a required text for GR5702. Be sure to get the second edition, which is a comprehensive update to D3 version 4. The first edition uses D3 version 3, which is not compatible. (The current version of D3 is actually v7. However, since differences between v4 and v5/v6/v7 are minimal, unless otherwise indicated in this guide, the code in IDVW2 will work with either.) We rely on the text heavily but also deviate from it in several ways. IDVW2 is written for graphics designers not data science students so the pain points are somewhat different. D3 is a JavaScript library, not a standalone language, so any time we refer to D3 we really mean D3/JavaScript, though it is not necessary to know JavaScript well before beginning; we will learn as we go. Most of the JavaScript we use is covered in IDVW2, though we also use some newer JavaScript options from ES5 and ES6, such as .map(), .filter(), arrow functions and template literals, that make coding easier (and more like R!)1 We use different examples, though you are strongly encouraged to study Murray’s code examples in addition to reading the text. Particularly through the first half, we don’t follow the text in order, so always refer to this guide first which will direct you to the pages of the text that you should read. This is very much a work-in-progress so please submit issues on GitHub to provide feedback and edit or add text by submitting pull requests. (Click the icon at the top of each page to get started. More detailed instructions are available on edav.info. If you would just like to view the source code, click the icon.) 0.1 Workflow A big hurdle to learning a new language is just getting setup. Often authors forget to mention what your programming environment should look like, what should be open on the screen. I will try not to do that and be as clear as possible so you know where you should be entering the code in the pages that follow. This task is somewhat complicated by the fact that we will be using a variety of workflow options. This section will serve as a reference guide; future sections will link back here as appropriate. All of our workflows require Google Chrome, so if you don’t have it already, download and install it. 0.1.1 JavaScript Console With this workflow we will open a web page–either online or local–in Chrome and run JavaScript in the Console. To view the Console, open Chrome DevTools by clicking View, Developer, JavaScript Console if you have a menu bar in Chrome, using a keyboard shortcut (Mac: option+command+j; Windows, Linux, Chrome OS: control+shift+J), or employing another one of the many options for doing so. The Console is one piece of a suite of tools available in the browser. With the DevTools open, your screen will look like this: The next chapter, Jump in the deep end, employs this workflow. 0.1.2 This book in the Console If you’re not reading the .pdf version, you can open DevTools on this very page. This is very convenient because not only to you not have to leave this book to practice D3, you can copy code blocks and paste them in the Console. In addition to opening DevTools (see above), close the side bar by clicking on the (“Toggle Sidebar”) icon on the top left of the page, to the left of the search icon, to give yourself more screen space. Let’s try it out. Open the JavaScript Console svg#demo Scroll so that both the blue rectangle above and the code chunk below are visible on your screen. Toggle the sidebar, open the Console, and then move the mouse onto the code block so the icon appears. Click on it to copy the code, paste it in the Console, and then press return. d3.select("svg#demo") .append("circle") .attr("cx", "-25") .attr("cy", "100") .attr("r", "20") .attr("fill", "red") .transition() .duration(3000) .attr("cx", "325") .remove(); Pretty neat. 0.1.3 Text editor This is a very basic local setup in which the same .html is open both in a text editor (if you don’t want to stray too far from home, use RStudio) and in a web browser (we will use Chrome), each on one half of your screen. The workflow is: make changes to the file in the text editor, save the changes and then refresh the page in the browser to see the updates. Keyboard shortcuts for saving and refreshing (on the Mac, command-s and command-r respectively) are very helpful. Let’s try an example: Download a copy of shapes.html by opening this page and clicking File, Save Page As… Open the file in a text editor of your choice on one half of your screen. On the other half of your screen open the same file in Chrome. As you make changes to the .html file, save the file and then refresh the browser to see the effects. Your screen should look like this: Ok, they’re not actually that new, but it takes a while for new JavaScript to catch on, mainly due to concern with maintaining compatibility with older browsers. Since D3 itself is not compatible with very old browsers, and since we can’t focus on everything at once, we are not going to concern ourselves with browser compatibility. If you are interested in this, caniuse.com is very helpful for looking up what works where.↩︎ "],["jump.html", "1 Quick demo 1.1 Get ready 1.2 Elements tab 1.3 Console tab 1.4 Modify elements 1.5 Add transitions 1.6 Add interactivity 1.7 Examples", " 1 Quick demo Let’s skip the explanations and start coding in D3 right now. Then we’ll go back and learn step by step. In this chapter we will work in the JavaScript Console (help). 1.1 Get ready If you don’t have it, install the Chrome browser. Download a copy of shapes.html by opening this file and choosing File, Save Page As… If Chrome is your default browser, open shapes.html by double clicking it. Otherwise, open Chrome first, click File, Open File…, and then choose shapes.html from the directory where you saved it. 1.2 Elements tab Open Chrome DevTools (help). Hover the mouse over various elements in the <body> ... </body> section. Observe the highlighted sections in the rendered web page on the left of the screen. Click on the mini black triangles to the left of the <body> and <svg> tags if needed to open these sections of the DOM tree. Your screen should look like this: Now try the reverse: right click on elements on the web page, choose “Inspect” and see what is highlighted in the Elements pane. Get comfortable with the connection between the code on the right and the rendered elements on the left. 1.3 Console tab Switch to the Console tab, next to the Elements tab. Let’s practice running some code. Note that the code is unrelated to the shapes.html web page that we have open. We will spend a lot of time in the Console since it’s interactive – think R console. Eventually we will switch to including JavaScript/D3 in .html or .js files and use the Console only for testing things out or debugging. Type the following lines of code at the prompt (>), press enter after each line–that is, after the semicolon (;)–and see what happens: 3 + 4; "3" + "4"; x = [1, 2, 3]; x[1]; x + 1; y = {a: 3, b: 4}; y["b"]; 1.4 Modify elements Now we’ll start using D3 to manipulate elements on the page. Try the following, by entering one line at a time in the Console as before: d3.select("circle").attr("cx", "200"); d3.select("circle").attr("cx", "500"); d3.select("circle").attr("cx", "100"); d3.select("circle").attr("r", "30"); d3.select("circle").attr("r", "130"); d3.select("circle").attr("r", "3"); d3.select("circle").attr("fill", "red"); d3.select("circle").attr("fill", "aliceblue"); d3.select("circle").attr("fill", "lightseagreen"); Note that “select” and “attr” are separate operations chained together with “.” – think pipe (|>) operator. Refresh the page. What happened? Go to Elements. Look at the value of the y1 attribute of the SVG <line> element. Go back to the Console and enter the following: d3.select("line").attr("y1", "10"); Switch back to Elements and observe. What happened? Stay in Elements and refresh the page. What happened to y1? Return to the Console to make style changes to the HTML elements: d3.select("h1").style("color", "purple"); d3.select("h2").style("font-size", "50px"); d3.select("h2").style("font-family", "Impact"); 1.5 Add transitions Try these: d3.select("svg").select("circle").transition().duration(2000).attr("cx", "400"); d3.select("svg").select("ellipse").transition().duration(2000).attr("transform", "translate (400, 400)"); d3.select("svg").select("line").transition().duration(2000).attr("x1", "400"); d3.select("svg").select("line").transition().duration(2000).attr("y1", "250"); d3.select("body").select("p").transition().duration(2000).style("font-size", "72px"); Experiment with more transitions. 1.6 Add interactivity Set up a function to turn the fill color to yellow: function goyellow() {d3.select(this).attr("fill", "yellow")}; Add an event listener to the circle that will be trigger a call to goyellow() on a mouseover: d3.select("svg").select("circle").on("mouseover", goyellow); Test it out. Add the same event listener to the ellipse. Test it out. Create a function goblue() that changes the fill color to blue. Add event listeners to the circle and ellipse that will trigger a call to goblue() on a mouseout. Test out your code. Try out a click event. (Note the use of an anonymous function.) d3.select("svg").select("line").on("click", function() {d3.select(this).attr("stroke-width", "10");}); Try another click event. What’s happening? d3.select("svg").on("click", function(event) {d3.select("text").text(`(${d3.pointer(event)})`)}); 1.7 Examples Check out this fun visualization by Yilan Chen (EDAV 2023) that started with shapes.html: Tricolor Dango "],["web.html", "2 Web tech 2.1 HTML 2.2 CSS 2.3 SVG 2.4 JavaScript 2.5 D3 2.6 HTML tree 2.7 Exercise : shapes", " 2 Web tech Read IDVW2, Chapter 3: Technology Fundamentals There is a lot of material in this chapter. It is worth making the effort to learn it now and start D3 with a solid foundation of elementary HTML/CSS/SVG/JavaScript. Here we examine shapes.html from Chapter 1 to see how the various technologies are combined into a single document. 2.1 HTML Note that shapes.html has an HyperText Markup Language or .html extension; HTML in fact provides the structure for the document. It has a <head> and <body> section. In the <head> section we use <script> tags to link to the D3 library: <script src="https://d3js.org/d3.v7.js"></script> HTML content is enclosed between opening an closing tags such as <h1> and </h1>. HTML class and ID attributes are included inside the opening tags: <h1 class=\"myclass\" id=\"myid\">This is an h1 header.</h1> 2.2 CSS CSS (Cascading Style Sheets) is used for styling web pages, and more importantly for our purposes, selecting elements on a page or in a graphic. We will generally work with internal style sheets since it’s simpler when starting out to have everything in one document. External style sheets, however, are generally the preferred method for web design. 2.2.1 Internal style sheet shapes.html has an internal style sheet: CSS style information appears in the <head> section marked off with <style> tags: <style type="text/css"> h1 {color:red;} /* CSS styling */ p {color:blue;} </style> Here we specify that all HTML <h1> headers should be red and all HTML paragraphs <p> should be blue. This is an example of an internal style sheet. Later we will consider alternatives: external style sheets and inline styling. Styling for coder designed classes is also specified in this section. For example, we could style a “formal” class as such: <style type="text/css"> .formal {color: red; font-size: 30px; font-family: Lucida Calligraphy; } </style> Note that classes are defined by the “.” before the name. 2.2.2 External style sheets External style sheets are .css files that contain styling information and are linked to with a <link> tag in the <head> section of an HTML document: <head> <link rel="stylesheet" href="style.css"> </head> External style sheets are the preferred way of styling as they can easily be modified without changing the web page; in fact, the motivation for CSS came from a desire in the early days of the internet to separate styling from content. Developers have the option now of choosing premade themes, which are shared through external style sheets. They can be quite complex. The .css file for the  Minty  theme from Bootswatch, for example, contains over 10,000 lines. CSS Zen Garden demonstrates the power of external style sheets: the same HTML document takes on very different looks depending on the stylesheet to which it is linked. 2.2.3 Inline styling With inline styling, styling is added to each tag individually: <span style="color: white; background-color: fuchsia; font-family: impact; font-size: 24px; border-style: solid; border-color: limegreen; border-width: 3px"> Styled inline </span> Styled inline This is how early web pages were styled. To take a step back in time, use developer tools to view the source code for the main page of www.dolekemp96.org, an old web site that has been maintained for historical purposes. As you can see, it’s a tedious way of writing content, which internal and external style sheets eliminate. Although you will not be adding inline styling manually, you will notice that when we select elements and change the styling with D3, the modifications are made inline. In other words, we do not make changes to the elements directly, not via a style sheet. 2.3 SVG SVG (Scalable Vector Graphics) is a human readable graphics format that facilitates manipulation of individual elements. You may be familiar with .svg files. Here we have SVG graphics within <svg> tags in the <body> section of the HTML document: <svg width="500" height="300"> <!-- some SVG --> <rect x="20" y="20" width="460" height="260" fill="lightblue"></rect> <circle cx="50" cy="75" r="20" fill="blue"></circle> <ellipse cx="175" cy="100" rx="45" ry="30" fill="green"></ellipse> <text x="150" y="200">(150, 200)</text> <line x1="250" y1="150" x2="300" y2="200" stroke="red" stroke-width="5"></line> </svg> (150, 200) There are very few SVG tags that you’ll need to know, and once we get going with D3, you will not have to code any SVG manually. It is worth doing a little to become familiar with the format and in particular to get used to the new location of the origin. 2.4 JavaScript JavaScript is the most common language for making web pages interactive. Code is executed when pages are opened or refreshed. So far we have run JavaScript in the Console, but have not included it in the web page itself. When we do so, it will be between <script> tags in the <body> section of the HTML document, or in a separate .js file. We will learn JavaScript on an as-needed basis. In terms of data, we will begin with simple arrays: const x = [3, 5, 1, 6, 7] In the Just Enough JS chapter, we cover more complex data structures and some methods for data manipulation. javascript.info is an excellent resource for expanding your knowledge beyond the basics. 2.5 D3 D3 (Data Driven Documents) is a JavaScript library well suited to interactive graphics. As such, it is also included between <script> tags in the <body> section. For D3 to work, you must link to the D3 library in the <head> section of the document. There seems to be a misconception that D3 is a high level language. It is not. You will be working on the pixel level to create graphics, including drawing your own axes and doing other things that you’re not used to doing if you’ve been working in R or Python. On the bright side, after D3, you will gain a new appreciation for base R graphics. You will write code such as plot(iris$Sepal.Length, iris$Sepal.Width, pch = 16, col = iris$Species, las = 1, xlab = \"Sepal.Length\", ylab = \"Sepal.Width\") and think: wow, there are axes! Amazing! It is legitimate to ask why you need to know D3 as a data scientist. Many if not most of you will not be coding in JavaScript from the ground up in your future careers. However, it’s a great way to learn how interactive graphics work under the hood, and will give you a solid foundation which you can draw on to tweak visualizations that you build with high level tools such as Plotly. 2.6 HTML tree While shapes.html appears as a single consistent document, it is actually comprised of multiple languages. HTML, CSS, and SVG are already there, and we will be adding JavaScript / D3 soon. Of note: An HTML document is composed of lines or sections set off with tags. In particular <style> ... </style>, <svg> ... </svg>, and <script> ... </script> indicate the inclusion of CSS, SVG, and JavaScript/D3 respectively. For D3 to work, you must link to a D3 library. To link to the online version, include this line: <script src=\"https://cdn.jsdelivr.net/npm/d3@7\"></script> or <script src=\"https://d3js.org/d3.v7.js\"></script>. Alternatively, you can download a copy of the library from https://d3js.org/getting-started#d3-in-vanilla-html–clicking on d3.v7.js or d3.v7.min.js will download the file. Then add the following to the <head> section of your .html file: <script src="d3.js"></script> There are two main sections. The <head> section contains the title, link to D3 library, and internal CSS. The <body> section contains HTML elements (<h1>, <p>, etc.), SVGs (between <svg>/</svg>tags) and JavaScript/D3 scripts (between <script>/<script>tags). Do not assume that if it works that it is correct; today’s browsers can be very forgiving. Comment syntax varies with language: <!-- single or multiline HTML or SVG comment --> /* single or multiline CSS comment */ // single line JavaScript comment /* JavaScript multiline comment */ 2.7 Exercise : shapes Download a copy of shapes.html by opening this page and clicking File, Save Page As… Set yourself up to work locally in a text editor help. (Developer Tools should not be open; we will not be using the Console.) Add an additional circle to the svg. Add styling to the internal style sheet to style circles. Add two additional paragraphs using the <p> tag. Add an ID attribute to one of the circles. Add a class attribute to two of the <p> tags. Use the internal style sheet to style paragraphs of the class you created in 5. Adjust additional elements as desired. Solution Contributed by Tracy Liu "],["d3console.html", "3 Modify, Add, Remove 3.1 Selections 3.2 Modify existing elements 3.3 Add elements 3.4 Remove elements 3.5 Exercise : green circles 3.6 Exercise : blue circles 3.7 Bind data… finally! 3.8 Exercise : data bind", " 3 Modify, Add, Remove Read IDVW2, Chapter 6: Drawing with Data. Skip pp. 89-96 as we will not be drawing bar charts with the divapproach. 3.1 Selections 3.1.1 Select by tag The ability to select elements on a page is key to being able to manipulate them. d3.select() will select the first match; d3.selectAll() will select all matches. d3.select("svg").select("circle"); selects the first circle in the order in which circles appear in the <svg> grouping. If there were more than one circle we could select them all with: d3.select("svg").selectAll("circle"); We can select HTML elements by tag in the same way: d3.select("body").select("h1"); d3.select("body").selectAll("h1"); 3.1.2 Select by class Classes are selected by adding a “.” before the class name: d3.select("svg").selectAll("circle.apple") This provides one method of selecting a certain collection of elements of the same type. 3.1.3 Select by ID IDs differ from classes in that they are unique identifiers. IDs are selected by adding a “#” before the ID: d3.select("svg").select("circle#henry"); 3.1.4 Store selections It is often helpful to store selections for later use. Here we store the svg selection in mysvg: const mysvg = d3.select("svg"); The JavaScript community is moving toward using let and const instead of var; we, however, will stick with var to be consistent with IDVW2. Of course you’re welcome to use const and let instead, and if so, may find these articles helpful: Let It Be - How to declare JavaScript variables and ES2015 const is not about immutability. Store circle selection in a variable: const svg = d3.select("svg"); const circ = svg.selectAll("circle"); 3.2 Modify existing elements Try out the code in this section with a downloaded copy of five_green_circles.html opened in Chrome and the Console visible. 3.2.1 Modify attributes link to get or set attribute API d3.select("circle").attr("r"); // see radius d3.select("circle").attr("r", "10"); // set radius to 10 3.2.2 Modify styles link to get or set style API d3.select("h1").style("color"); d3.select("h1").style("color", "blue"); It is often difficult to remember whether to use .attr() or .style() In general, properties such as position on the SVG, class, and ID are attributes, while decorative properties such as color, font, font size, etc. are styles. However, in some cases, you can use either. For example, the following both make the circle blue: d3.select("circle").attr("fill", "blue"); d3.select("circle").style("fill", "blue"); The first will add a fill=\"blue\" attribute to the <circle> tag, while the latter will add style=\"fill: blue;\". All is well and good until you find yourself with both in the same tag, in which case the style property will take precedence. The bottom line: don’t mix the two options because it can cause problems. To further complicate matters, .style() is just shorthand for .attr(\"style\", \"...\") so the following are in fact equivalent: d3.select("circle").style("fill", "blue"); d3.select("circle").attr("style", "fill: blue;"); In other words, style is an attribute! 3.2.3 Modify text This section is interactive: You can hover over code as directed to observe effects. The interactivity is enabled by D3 scripts that are included in the .Rmd source file of this page. If you’re interested you can view these scripts by either clicking on the eye icon above or opening Developer Tools in Chrome. In either case, look for the code between the <script> </script> tags. HTML text .fancy { color: red; font-family: garamond; font-size: 30px; } <p id="typo" class="fancy">Manhatten</p> Manhatten Hover to execute this code (and fix the typo): d3.select("#typo").text("Manhattan"); SVG text <svg width="500" height="100"> <rect width="500" height="100" fill="#326EA4"></rect> <text id="svgtypo" x="50" y="70" fill="white" font-weight="bold" font-size="40px"> Web scrapping is fun.</text> </svg> Hover on this SVG to execute the code below it (and fix the typo): Web scrapping is fun. d3.select("#svgtypo").text("Web scraping is fun."); The SVG <text> tag can be tricky. It differs from HTML text tags (<p>, <h1>, <h2>, etc.) in that it has x and y attributes that allow you to position text on an SVG canvas. Unlike HTML, the fill attribute controls the color of the text. Compare: d3.select("p").style("color", "red"); // HTML d3.select("text").attr("fill", "red"); // SVG 3.2.4 Move SVG text <svg width="600" height="100"> <rect width="600" height="100" fill="#326EA4"></rect> <text id="moveleft" x="200" y="70" fill="white" font-weight="bold" font-size="40px"> I want to move left.</text> </svg> Hover on this SVG to execute the code below it: I want to move left. d3.select("#moveleft").attr("x", "20").text("Thanks, now I'm happy!"); 3.3 Add elements 3.3.1 HTML Continue trying out code with five_green_circles.html open in Chrome. Or download the file and open it. The following adds a <p> tag but doesn’t change how the page looks, since there’s no text associated with it. d3.select("body").append("p"); To add text, use .text(): d3.select("body").append("p").text("This is a complete sentence."); To debug adding an element, go to the Elements tab to see what was added and where. If an element is in the wrong place in the HTML tree, it will not be visible. 3.3.2 SVG Likewise, here we add a <circle> to the <svg>, but we can’t see it since it has no attributes. d3.select("svg").append("circle"); Adding attributes will create visible circles: d3.select("svg").append("rect").attr("x", "0").attr("y", "0") .attr("width", "500").attr("height", "400").attr("fill", "lightblue"); d3.select("svg").append("circle").attr("cx", "200") .attr("cy", "100").attr("r", "25").attr("fill", "orange"); d3.select("svg").append("circle").attr("cx", "300") .attr("cy", "150").attr("r", "25").attr("fill", "red"); We can use a saved selection to assist in creating a new element: (IDVW2, pp. 97-98) mysvg = d3.select("svg"); mysvg.append("circle").attr("cx", "250").attr("cy", "250").attr("r", "50") .attr("fill", "red"); 3.4 Remove elements These methods will remove matching elements in order, starting with the first find in the document. 3.4.1 HTML d3.select("p").remove(); 3.4.2 SVG d3.select("svg").select("circle").remove(); d3.select("svg").selectAll("circle").remove(); 3.5 Exercise : green circles Return to five_green_circles.html, open Developer Tools, and do the following in the Console with D3: Select the circle with ID “henry” and make it blue. Select all circles of “apple” class make them red. Select the first circle and add an orange border (use attribute “stroke”), and stroke width (“stroke-width”) of 5. Select all circles of “apple” class and move them to the middle of the svg. Solution 3.6 Exercise : blue circles Return to six_blue_circles.html, open Developer Tools, and execute Steps 1-4 one at a time in the Console. After Step 4, refresh the page to go back to Step 1 if so desired. (You do not need to create a loop as in the visual.) This exercise is provided as a challenge. It’s fine to skip this exercise and move on to the next section. Move all the circles to the right. Move them back to the left and change their color. In a text editor, add an id to the third circle in six_blue_circles.html, save the file, and then in the Console, move only that circle to the right. Move all the circles to the middle of the screen, then move them all to the same location. Solution 3.7 Bind data… finally! (IDVW2, pp. 98-108) To follow along with the code in this section, download and open six_blue_circles.html. Bind data: d3.select("svg").selectAll("circle").data([90, 230, 140, 75, 180, 25]); Check data binding: d3.select("svg").selectAll("circle").data(); Set x-coordinate of each circle to data value using arrow function: d3.select("svg").selectAll("circle").attr("cx", d => d); Set x-coordinate of each circle to data value with a JavaScript function: d3.select("svg").selectAll("circle").attr("cx", function(d) {return d;}); We’ll bind a new set of data to the circles, this time storing the dataset in a variable: const dataset = [50, 80, 110, 140, 170, 200]; We’ll also store a selection of all circles before binding the data: const circ = d3.select("svg").selectAll("circle"); And now, the data bind: circ.data(dataset); Nothing appears to have happened; the circles remain the same and there is no evidence of any changes looking at the circles in the DOM (see Elements tab). We can check that the data are indeed bound with: circ.data(); // now we see data Modify elements w/ stored selections, bound data: circ.attr("cx", function(d) {return d;}); circ.attr("cx", function(d) {return d/2;}); circ.attr("cx", function(d) {return d/4;}).attr("r", "10"); Same as above, using arrow functions: circ.attr("cx", d => d); circ.attr("cx", d => d/2); circ.attr("cx", d => d/4).attr("r", "10"); Note that if we bind a new set of data to the DOM elements, the original set will be overwritten: const newdata = [145, 29, 53, 196, 200, 12]; circ.data(newdata); circ.transition() .duration(2000) .attr("cx", d => 2*d); 3.8 Exercise : data bind Return to six_blue_circles.html, open Developer Tools, and practice binding data to the circles and modifying the circles based on the data as in the examples above. "],["update-enter-and-exit.html", "4 Update, Enter, and Exit 4.1 Lecture slides 4.2 Use exit selection to remove elements 4.3 Use enter selection to add elements 4.4 Data / enter / append sequence 4.5 Exercise : horizontal bar chart 4.6 Merge selections 4.7 Exercise : merge 4.8 Groups 4.9 General Update Pattern (with merge) 4.10 General Update Pattern (with join) 4.11 Exercise: : functions 4.12 Exercise : vertical bar chart", " 4 Update, Enter, and Exit Read: IDVW2, Chapter 9, pp. 178-184; Chapter 12, pp. 231-249 4.1 Lecture slides D3 Data Bind Jump to data/enter/append Jump to general update pattern 4.2 Use exit selection to remove elements a.k.a. more DOM elements than data values We’ll start with six circles and remove some. Open six_blue_circles.html in Chrome and open the JavaScript Console. Let’s bind four data values to the six circles: d3.select("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: const circ = d3.select("svg") .selectAll("circle") .data([123, 52, 232, 90]); Let’s look at the exit selection: circ.exit(); Try this: circ.attr("fill", "red"); What happened and why? Now try this: circ.exit().attr("fill", "purple"); What happened and why? What do you think this will do? Try it. circ.exit().transition().duration(2000).remove(); Create a new variable circ2 and compare it to circ: const circ2 = d3.selectAll("circle"); circ.data(); circ2.data(); circ.exit(); circ2.exit(); What’s going on? 4.3 Use enter selection to add elements a.k.a. more data values than DOM elements We’ll start with six_blue_circles.html in Chrome and add some circles. First, let’s bind new data to the circles: const circ = d3.select("svg") .selectAll("circle") .data([123, 52, 232, 90, 34, 12, 189, 110]); And look at the enter selection: circ.enter(); How many placeholders are in the enter selection? Let’s add circles for each of these placeholders: circ.enter() .append("circle") .attr("cx", "100") .attr("cy", (d, i) => i * 50 + 25) .attr("r", "20") .attr("fill", "blue"); Try this: circ.transition() .duration(3000) .attr("cx", "400"); What do you need to do to act on all of the circles? d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cy", (d, i) => (i * 50) + 25) .attr("cx", "200"); 4.4 Data / enter / append sequence We’ll start with nothing–not even an SVG–and add elements with the data / enter / append sequence. Work in the Console on this page (help). Open the JavaScript Console The SVG will be added here: d3.select("div#dea") .append("svg") .attr("width", "400") .attr("height", "250"); Create an array of values: const specialdata = [75, 150, 200]; Add rectangles: d3.select("svg") .selectAll("rect") .data(specialdata) .enter() .append("rect") .attr("x", d => d) .attr("y", d => d) .attr("width", "50") .attr("height", "30") .attr("fill", "pink"); 4.4.1 Labels Note that we can also label the rectangles with the data value: d3.select("svg") .selectAll("text") .data(specialdata) .enter() .append("text") .attr("x", d => d + 25) .attr("y", d => d + 25) .text(d => d) .attr("fill", "blue") .attr("text-anchor", "middle"); 4.5 Exercise : horizontal bar chart Save a copy of this exercise and open it in your text editor. Create a horizontal bar chart with bar widths equal to the data values stored in bardata. Do so by replacing all the “ADD’s” with constants or functions and then uncommenting those lines. const bardata = [300, 100, 150, 225, 75, 275]; It should look like this: Solution 4.6 Merge selections We now know how to work separately with the update, enter, and exit selections. Often in practice we wish to do the same thing or almost the same thing with the enter and update selections. That is where .merge() comes in. If we merge the update and enter selections we don’t have to repeat our code. Open six_blue_circles.html in Chrome. Run the following code in the Console: const newdata = [123, 52, 232, 90, 34, 12, 189, 110]; const svg = d3.select("svg"); const circ = svg.selectAll("circle") .data(newdata); circ.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) .transition() .duration(2000) .attr("cx", "200"); Note the pattern: Create a data array Store the svg selection Store the data bind in X X.enter() .append(some shape) *add attributes* // acts on enter selection only (no transitions!) .merge(X) *attributes, other stuff* // acts on enter and update selections Do not include transitions in a stored selection! 4.7 Exercise : merge Open this bar chart in Chrome and work in the Console. (You don’t have to download it.) All of your solutions should begin with: Creating a data array (ex. const dataset = [1, 2, 3];) Selecting the svg and storing it (const svg = d3.select(\"svg\");) Binding the data and storing it (ex. const bars = svg.selectAll(\"rect\").data(dataset));) Change the data to any six other values and update the lengths of the bars. Bind a new dataset, newbardata to the bars, update the bar lengths, and remove any extra bars. newbardata = [250, 125, 80, 100]; 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]; 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. Add text labels inside the bars at the right end with the length of the bar in pixels. Solution 4.8 Groups Open six_blue_circles.html in Chrome. Run this code in the Console: const specialdata = [100, 250, 300]; const bars = d3.select("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: const svg = d3.select("svg"); const specialdata = [100, 250, 300]; const bars = d3.select("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: d3.select("svg") .select("g#rects") .selectAll("rect") .attr("fill", "purple"); and d3.select("svg") .selectAll("rect") .attr("fill", "purple"); 4.9 General Update Pattern (with merge) Open Developer Tools on this page. Create a function in the Console: function changedata(data) { d3.select("svg#gup") .selectAll("rect") .data(data) .attr("width", d => d); } Test it out: changedata([258, 373, 278, 9, 72, 96]); What happens if there are too many data values? changedata([196, 360, 283, 390, 46, 56, 152]); Let’s use the enter selection to add new bars in this case: function changedata(data) { const bars = d3.select("svg#gup") .selectAll("rect") .data(data); // bars is the update selection bars.enter() .append("rect") .attr("x", "30") // until merge, acts on .attr("y", (d, i) => i * 50) // enter selection only .attr("height", "35") .attr("fill", "lightgreen") .merge(bars) // merge in the update selection .attr("width", d => d); // acts on all bars } What happens if we have more bars than data values? changedata([325, 116, 25]); Let’s add to the function to remove the extra bars in this case: function changedata(data) { const bars = d3.select("svg#gup") .selectAll("rect") .data(data); // bars is the update selection bars.enter() .append("rect") .attr("x", "30") // until merge, acts on .attr("y", (d, i) => i * 50) // enter selection only .attr("height", "35") .attr("fill", "lightgreen") .merge(bars) // merge in the update selection .attr("width", d => d); // acts on all bars bars.exit() .remove(); } Try: changedata([271, 49, 389]); VOILA! We have created the D3 General Update Pattern! It is covered in IDVW in the “Other Kinds of Data Updates” section on pp. 178-186 in Chapter 9. (The earlier part of Chapter 9 deals with data updates in which the number of DOM elements remains the same.) Note that the General Update Pattern changed with D3 Version 4 so avoid examples from Version 3. Also available here for download: general_update_pattern.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <script id="s1"> // Create svg and initial bars const svg = d3.select("body") .append("svg") .attr("width", "500") .attr("height", "400"); const bardata = [300, 100, 150, 225, 75, 275]; const bars = svg.selectAll("rect") .data(bardata); bars.enter().append("rect") .attr("x", "30") .attr("y", (d, i) => i*50) .attr("width", d => d) .attr("height", "35") .attr("fill", "lightgreen"); // General Update Pattern function update(data) { const bars = svg.selectAll("rect") // data join .data(data); bars.enter() .append("rect") // add new elements .attr("x", "30") .attr("y", (d, i) => i*50) .attr("width", d => d) .attr("height", "35") .attr("fill", "yellow") .merge(bars) // merge .transition() .duration(2000) .attr("width", d => d) .attr("fill", "orange"); bars.exit().remove(); // remove extra elements } </script> </body> </html> 4.10 General Update Pattern (with join) Optional This is a newer method–introduced in v5–which simplifies the general update pattern by automatically adding elements for the enter selection, removing elements for the exit selection, merging the enter and update selections and then acting on them all with .join(). The update pattern above could be replaced with the following: function changedata2(data) { const svg = d3.select("svg#gup") svg.selectAll("rect") .data(data) .join("rect") // need "rect" for appending elements .attr("x", "30") .attr("y", (d, i) => i * 50) .attr("height", "35") .attr("fill", "lightgreen") .attr("width", d => d); } Try: changedata2([271, 49, 389]); With .join() you can get more granular with enter, update, and exit selections as we did previously. changedata3() is equivalent to changedata2(): function changedata3(data) { const svg = d3.select("svg#gup") svg.selectAll("rect") .data(data) .join( enter => enter.append("rect") .attr("x", "30") .attr("y", (d, i) => i * 50) .attr("height", "35") .attr("width", d => d) .attr("fill", "lightgreen"), update => update .attr("width", d => d), exit => exit.remove() ); } Generally, however, unless you have transitions, you will not need to control the enter, exit and update selections separately. 4.11 Exercise: : functions Open general_update_pattern.html and practice running the update() function with different datasets in the Console. For example: update([100, 200, 300]); Solution 4.12 Exercise : vertical bar chart Save a copy of this exercise and open it in your text editor. Create a vertical bar chart with bar heights equal to the data values stored in bardata. Do so by replacing all the “ADD’s” with constants or functions and then uncommenting those lines. Solution "],["just-enough-js.html", "5 Just Enough JS 5.1 Arrays of arrays 5.2 Arrays of objects 5.3 .map() 5.4 D3 sorting 5.5 D3 statistics 5.6 D3 + .map()", " 5 Just Enough JS Basics: IDVW, pp. 36-52 Before JavaScript ES6, the ‘var’ keyword was used to declare a variable. Variables declared using the ‘var’ keyword are either globally or functionally scoped, they do not support block-level scope. Therefore, in JavaScript ES6, the ‘let’ keyword and ‘const’ keyword were introduced. The ‘let’ keyword deals with a block scope. It can be reassigned but cannot be redeclared. The ‘const’ keyword is also blocked scoped. It cannot be reassigned and cannot be redeclared. As a general rule, you should always declare variables with ‘const’, if you realize that the value of the variable needs to change, go back and change it to ‘let’. For more detailed information regaring ‘var’, ‘let’ and ‘const’, please see Difference between var, let, and const keyword in JavaScript objects, arrays, arrays of objects, functions (and other things) 5.1 Arrays of arrays Open the JavaScript Console // try me in the Console const array_dataset = [[100, 75, 30], [200, 125, 20]]; d3.select("svg#arrays") .selectAll("circle") .data(array_dataset) .enter() .append("circle") .attr("cx", d => d[0]) .attr("cy", d => d[1]) .attr("r", d => d[2]) .attr("fill", "red"); svg#arrays 5.2 Arrays of objects // Try me in the Console const object_dataset = [ {cx: 100, cy: 150, fill: `red`}, {cx: 200, cy: 100, fill: `blue`} ]; d3.select("svg#objects") .selectAll("circle") .data(object_dataset) .enter() .append("circle") .attr("cx", d => d.cx) .attr("cy", d => d.cy) .attr("r", "30") .attr("fill", d => d.fill); svg#objects See also: JavaScript Array of Objects Tutorial 5.3 .map() What’s the issue? In R many operations are vectorized: sqrt(3) ## R output ## [1] 1.732051 x <- c(3, 5, 7) sqrt(x) ## R output ## [1] 1.732051 2.236068 2.645751 Not so in JavaScript: Math.sqrt(3); // Try me in the Console const x = [3, 5, 7]; // Try me in the Console Math.sqrt(x); // Doesn't work... 5.3.1 Simple arrays Use .map() to operate on each array element separately. The concept is similar to lapply() or purrr::map(), but unlike in R, it’s needed for simple arrays. R x <- c(3, 5, 7) sqrt(x) ## R output ## [1] 1.732051 2.236068 2.645751 JavaScript Do something to every element of a simple array: // take the square root of each element const x = [3, 5, 7]; // try me x.map(Math.sqrt); // multiply each element by 3 [4, 10, 12].map(d => d*3); // try me // multiply each element by 3 [4, 10, 12].map(function(d) {return d*3;}); // try me // multiply each element by its index [10, 20, 30, 40].map((d, i) => d*i); // try me R: Sum two arrays # sum two arrays x <- 1:3 y <- 4:6 x + y ## R output ## [1] 5 7 9 JavaScript: Sum two arrays // sum two arrays const x = [1, 2, 3]; const y = [4, 5, 6]; x + y // try me... what went wrong? // sum two arrays const x = [1, 2, 3]; const y = [4, 5, 6]; x.map((d, i) => d + y[i]); // try me 5.3.2 Arrays of arrays Do something to the first item of every element of a nested array: [[1, 2], [3, 4]].map(d => Math.sqrt(d[0])) // try me Sum up all items in each element of the array: [[1, 2, 3], [4, 5, 6]].map(d => d[0] + d[1] + d[2]); // try me Created a nested array out of a simple array: [10, 20, 30].map(d => [d, Math.pow(d, 2)]); 5.3.3 Create arrays of objects Create an array of objects out of a simple array (note the parentheses around the object): [10, 20, 30].map(d => ({n: d, nsq: Math.pow(d, 2)})); // try me [10, 20, 30].map((d, i) => ({index: i, value: d})); // try me 5.4 D3 sorting Use d3.sort() rather than plain JavaScript options. const y = [3, 1, 5, 12, 7]; // try me d3.sort(y); 5.5 D3 statistics link to API D3 brings us back to familiar ground with functions that take an array and return a single value. Here are D3 functions with the same names and behavior as their R equivalents: R D3 min(x) d3.min(x) max(x) d3.max(x) sum(x) d3.sum(x) mean(x) d3.mean(x) median(x) d3.median(x) A few with different names: R D3 range(x) d3.extent(x) var(x) d3.variance(x) sd(x) d3.deviation(x) d3.quantile() takes a single value for p, not an array as in R. (In earlier versions of D3 it was necessary to sort the array before finding quantiles, but this is no longer the case.) R D3 quantile(x) d3.quantile(x, p) Thus for a single quantile we have: const x = [12, 34, 1, 43, 90, 72]; // try me d3.quantile(x, .25); https://github.com/d3/d3/blob/main/API.md#statistics 5.6 D3 + .map() D3 statistics functions combined with .map() can be helpful in a variety of situations. Vectorizing a parameter, for example to mimic quantile(x) in R: R x <- c(1, 12, 34, 43, 72, 90); quantile(x) ## R output ## 0% 25% 50% 75% 100% ## R output ## 1.00 17.50 38.50 64.75 90.00 JavaScript const x = [1, 12, 34, 43, 72, 90]; // try me [0, .25, .5, .75, 1].map(p => d3.quantile(x, p)); Sum up the first item of all elements in an array of arrays: R l <- list(c(100, 200, 40), c(300, 150, 20)) sum(purrr::map_dbl(l, ~.x[1])) ## R output ## [1] 400 JavaScript const dataset = [[100, 200, 40], [300, 150, 20]]; // try me d3.sum(dataset.map(d => d[0])); Sum up all items in each array to create a simple array: R l <- list(c(100, 200, 40), c(300, 150, 20)) purrr::map_dbl(l, ~sum(.x)) ## R output ## [1] 340 470 JavaScript const dataset = [[100, 200, 40], [300, 150, 20]]; // try me dataset.map(d => d3.sum(d)); "],["scales-and-axes.html", "6 Scales and Axes 6.1 Scales 6.2 Margins 6.3 Axes 6.4 Bar chart with categorical labels", " 6 Scales and Axes 6.1 Scales 6.1.1 Lecture slides Scales 6.1.2 Practice See: IDVW2, Chapter 7: Scales Practice creating an ordinal scale in the Console: Open the JavaScript Console const myscale = d3.scaleBand() .domain([0, 1, 2, 3, 4]) .range([0, 100]); myscale(1); Try other numbers: myscale(3);, myscale(2.5);, myscale(7);, etc. Add inner padding and try again. More on band scales here: https://d3js.org/d3-scale/band *Be sure to use d3.scaleBand(), not d3.scaleOrdinal() for this use case. 6.1.3 Exercise : vertical bar chart d3.scaleBand() IDVW2 Chapter 9, pp. 150-153 Create the vertical bar chart shown below by filling in the lines marked ADD in this file and uncommenting them. (Note that we are not yet employing a linear scale for the y-axis.) Solution d3.scaleLinear() In the next graph, d3.scaleLinear() is added to create a yScale function to convert bar heights to pixels. Change the data and observe how the bars are resized to fit on the SVG. Code for download 6.2 Margins 6.2.1 Lecture slides Margins “Margin convention” const w = 500; const h = 400; const margin = {top: 25, right: 0, bottom: 25, left: 25}; const innerWidth = w - margin.left - margin.right; const innerHeight = h - margin.top - margin.bottom; 6.2.2 Bar chart with margins Code for download 6.3 Axes See: IDVW2, Chapter 8: Axes 6.3.1 Lecture slides Axes 6.3.2 Bar chart with axes Code for download Practice changing the data and seeing what happens. 6.4 Bar chart with categorical labels Code for download "],["interactivity.html", "7 Interactivity 7.1 Binding event listeners to SVG elements 7.2 Separating the function and event listener 7.3 HTML buttons 7.4 Radio buttons 7.5 Dependent event listeners", " 7 Interactivity Read: IDVW2, Chapter 10 Interactivity 7.1 Binding event listeners to SVG elements (100, 150) It’s helpful to think carefully about what you want to happen when an event listener is triggered and what information you need. Open Developer Tools and try these in the Console. Note that event management changed in v6 so code written for earlier versions of D3 will not work. 7.1.1 Do something unrelated to the element that received the event d3.select("svg") .on("click", function () { d3.select("svg") .append("text") .attr("x", "100") .attr("y", "40") .text("Hello World"); }); 7.1.2 Change an attribute of the element that received the event d3.select("line") .on("click", function() { d3.select(this) .attr("stroke-width", "10"); }); In the context of event handlers, “this” is the element that received the event, a.k.a. what you clicked on if it’s a click event. An alternative (\\(\\geq\\) v6, see link above) is to pass the event and access the element with event.currentTarget: or d3.select("line") .on("click", function(event) { d3.select(event.currentTarget) .attr("stroke", "yellow"); }); 7.1.3 Get the value of an attribute of the element that received the event d3.select("circle") .on("click", function(event) { const rad = d3.select(event.currentTarget).attr("r"); d3.select("text") .text(`The radius is ${rad} pixels.`); }); 7.1.4 Do something with the data bound to the element that received the event d3.select("circle") .data([{s: "red", sw: "15"}]) .on("click", function(event, d) { d3.select(event.currentTarget) .attr("stroke", d.s) .attr("stroke-width", d.sw); }); Note that starting with v6, the data is the 2nd parameter to be passed: function(event, d). In addition, note that you do not need to pass d again when accessing the data: for example we use d.s not d => d.s. As in the previous example, d3.select(this) can be used instead of d3.select(event.currentTarget). Try changing the data value bound to the circle with d3.select(\"circle\").datum(\"10\") and clicking again. 7.1.5 Get the svg location of the event d3.select("svg") .on("click", function(event) { d3.select("text") .text(`(${d3.pointer(event).map(Math.round)})`) }); (Up to v5, d3.mouse(this) was used instead of d3.pointer(event).) 7.2 Separating the function and event listener Examples function goyellow() { d3.select(this) .attr("fill", "yellow") }; d3.select("circle") .on("mouseover", goyellow); 7.3 HTML buttons <button type="button" onclick="showdate()">Click for date</button> function showdate() { console.log(Date()); } Click for date 7.3.1 Exercise Add buttons as indicated to this file. 7.4 Radio buttons HTML: <p id="color" style="background-color: silver; color: white;"> Please select your favorite primary color:</p> <input type="radio" name="fav_color" value="red">red</input> <input type="radio" name="fav_color" value="blue">blue</input> <input type="radio" name="fav_color" value="yellow">yellow</input> Note: type is always radio for radio buttons name is shared for a group of radio buttons value is unique JavaScript: d3.selectAll('input[name="fav_color"]') .on("click", function(event) { var favcolor = event.currentTarget.value; d3.select("p#color").style("color", favcolor); }); Please select your favorite primary color: red blue yellow 7.5 Dependent event listeners In these examples, the behavior or existence of one event listener depends on another. 7.5.1 Global variable example Here the circle click behavior depends on the value of the radio button: if the “Move left” radio button is checked, the circle will move left when clicked. If the “Move right” radio button is checked, the circle will move right when clicked. A global variable is used to keep track of the radio button value. The event listener on the circle conditions the behavior on the value of this global variable. Click the circle.  Move left  Move right svg#radio // global variable keeps track of which radio button is clicked let action = "left"; d3.select("div#rad") .selectAll("input") .on("click", function() { action = d3.select(this).node().value; }); // circle click behavior depends on value of "action" d3.select("svg#radio").select("circle") .on("click", function () { let cx_new; if (action == "left") { cx_new = +d3.select(this).attr("cx") - 50; if (cx_new < 20) cx_new = 20; } else { cx_new = +d3.select(this).attr("cx") + 50; if (cx_new > 280) cx_new = 280; } d3.select(this) .transition() .duration(500) .attr("cx", cx_new); }); 7.5.2 Turn off event listener In this example, the event listeners on the squares are turned on or off depending on the value of the radio button. Event listeners can be removed by setting the behavior to null. Click a square.  Red active  Blue active svg#radio2 // movement function const jump = function () { d3.select(this).transition().duration(500) .attr('y', '0') .transition().duration(500).ease(d3.easeBounce) .attr('y', '75'); }; // initial setup: add event listener to red square d3.select("svg#radio2") .select("rect#red") .on("click", jump); // switch event listeners if radio button is clicked d3.select("div#rad2").selectAll("input") .on("click", function () { if (d3.select(this).node().value == "blue") { d3.select("svg#radio2").select("rect#blue").on("click", jump); d3.select("svg#radio2").select("rect#red").on("click", null); } else { d3.select("svg#radio2").select("rect#red").on("click", jump); d3.select("svg#radio2").select("rect#blue").on("click", null); } }); "],["transitions.html", "8 Transitions 8.1 Examples 8.2 Do this 8.3 Not this 8.4 Strategy 8.5 Exercise : Bar chart with transitions", " 8 Transitions Read IDVW2, Chapter 9: transitions section (pp. 158-178) 8.1 Examples Open Developer Tools and try in the Console: d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cx", "275"); d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cx", "25") .attr("fill", "green"); 8.2 Do this Run simultaneous transitions on different selections: d3.select("svg").selectAll("circle#henry").transition() .duration(2000).attr("cx", "275"); d3.select("svg").selectAll("circle.apple").transition() .duration(2000).attr("cx", "25"); Run sequential transitions on the same selection in one chain: d3.select("svg").selectAll("circle") .transition().duration(2000).attr("cx", "275") .transition().duration(2000).attr("cx", "25"); Transition from something to something: d3.select("svg").append("circle") .attr("cx", "200") .attr("cy", "100") .attr("r", "5") .attr("fill", "lightblue") .transition() .duration(4000) .attr("r", "25") .attr("fill", "blue"); 8.3 Not this DO NOT run two transitions on the same selection at the same time (see p. 172). (What works in the Console will not work in a script.) d3.select("svg").selectAll("circle").transition() .duration(2000).attr("cx", "250"); d3.select("svg").selectAll("circle").transition() .duration(2000).attr("cx", "75"); DO NOT transition from nothing to something: d3.select("svg").append("circle") .transition() .duration(2000) .attr("cx", "200") .attr("cy", "100") .attr("r", "25") .attr("fill", "red"); DO NOT store a selection with a transition (it’s no longer a selection with the transition): Try this: const circ = d3.select("svg") .selectAll("circle") .data([50, 95, 100, 200, 50, 150, 250]) .enter() .append("circle") .attr("cx", d => d) .attr("cy", "100") .attr("fill", "blue") .attr("r", "0") .transition() .duration(2000) .attr("r", "25"); And then this: circ.attr("fill", "green"); DO NOT put a transition before a merge: d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cx", "300") .merge("oldcirc") .attr("fill", "green"); BE AWARE that not everything transitions (for example, text doesn’t.) 8.4 Strategy Example 1 Think carefully about what you want to happen, and then decide what goes before and after the transition. Add bar Remove bar Plan what you want to happen: new bars appear on the right side with orange fill new bars slide into place from the right as old bars are repositioned new bars transition to blue removed bars transition to right before disappearing 8.5 Exercise : Bar chart with transitions Download and make changes to bar_transition.html in a text editor so the transitions work as shown below. Solution code for download rendered version Further reading: Working with Transitions. "],["object.html", "9 Object Constancy 9.1 Lecture slides 9.2 No object constancy 9.3 Object constancy", " 9 Object Constancy 9.1 Lecture slides object_constancy.pdf 9.2 No object constancy Transitions  Off  On Add bar Remove bar (right) Remove bar (left) Of note: Rather than smoothly transitioning off to the left, all bars are resized when “Remove bar (left)” is clicked When \"Remove bar (right) is clicked, the bar on the right immediately disappears, and then the remaining bars transition to their new places to the right. Standalone version: no_object_constancy.html 9.3 Object constancy Transitions  Off  On Add bar Remove bar (right) Remove bar (left) Of note: Bars now smoothly transition off to the left and right Standalone version: object_constancy.html 9.3.1 Practice joining data by key Open the JavaScript Console Try the following: Create an svg with four text elements: const dataset = [{key: 12, x: 163, y: 200}, {key: 14, x: 206, y: 304}, {key: 16, x: 452, y: 152}, {key: 18, x: 321, y: 254}]; const svg = d3.select("#key").append("svg") .attr("width", "600").attr("height", "400"); svg.append("rect").attr("width", "600") .attr("height", "400").attr("fill", "aliceblue"); svg.selectAll("text") .data(dataset, d => d.key) .enter() .append("text") .attr("x", d => d.x) .attr("y", d => d.y) .text(d => `key: ${d.key}`); Bind a new dataset by key: const svg = d3.select("#key").select("svg"); const dataset = [{key: 12, x: 100, y: 200}, {key: 16, x: 250, y: 300}]; svg.selectAll("text") .data(dataset, d => d.key) .exit() .remove(); Then: svg.selectAll("text") .attr("x", d => d.x) .attr("y", d => d.y); And another one: const svg = d3.select("#key").select("svg"); const dataset = [{key: 23, x: 300, y: 150}, {key: 5, x: 450, y: 270}, {key: 16, x: 200, y: 250}]; const databind = svg.selectAll("text") .data(dataset, d => d.key); databind .enter() .append("text") .merge(databind) .attr("x", d => d.x) .attr("y", d => d.y) .text(d => `key: ${d.key}`); databind.exit().remove(); Experiment with other data binds. "],["reading-files.html", "10 Reading files 10.1 Promises 10.2 Local server 10.3 Other local options 10.4 Hosting online", " 10 Reading files As you’ve surely noticed by this point, many things in JavaScript operate on an asynchronous basis. Code is not executed linearly from beginning to end but rather in response to various triggers. For example, event listeners behave asynchronously: code will execute only if a mouse click event occurs. The benefit to reading files asynchronously is that we don’t have to wait to while a file loads for other things to happen. It would be very frustrating to navigate to a new web page and have to wait for all the scripts to finish before we could do anything on the page. 10.1 Promises Loading data is one area where D3 v5 introduces major changes from D3 v4. While v4 uses callbacks, v5 switches to promises, as promises facilitate cleaner and more flexile code than callbacks. The concept is simple. We want to control what code needs to wait until data loaded to be executed and what doesn’t. We can do that with the following structure: const rowConverter = function (d) { return { disp: +d.disp, mpg: +d.mpg, carname: d.carname, cylcolor: d.cylcolor } }; d3.csv("https://raw.githubusercontent.com/jtr13/d3book/main/data/mtcars.csv", rowConverter) .then(function(data) { // stuff that requires the loaded data }) .catch(function(error) { // error handling }); The row converter function is used to select variables and change data types (“+” converts to floating point). d3.csv() returns a promise. If the promise is resolved, the .then() function will execute; if the promise is rejected, the .catch() function will execute. Forget the mindset that you read files and store them in variables for later use. It doesn’t work that way here. The data is read in and acted on immediately. If most of the code requires loaded data, then most of the code will appear in the .then() method. A simple example of loading data in v5 can be found in this block. In contrast to the example above, an anonymous row converter function (with arrow functions) is used instead of calling a separate row converter function. Note as well that it’s not necessary to include all variables in the row converter as this author has done. For example, you could delete all the variables that aren’t used, so that the row converter in the d3.csv line becomes: d => ({ HighwayMpg: parseInt(d.HighwayMpg), Horsepower: parseInt(d.Horsepower), }) You will see that the code still works. For more about d3.csv(), see the d3.fetch API. 10.2 Local server Note: As long as you read from online sources as in the example above, you do not need to set up a local server. For security reasons, Chrome does not let you read local files. To be able to do so, you can run a local server. One option is http-server. Follow the instructions to install http-server, navigate in a terminal to the directory with your html file, and then enter http-server: joycerobbins@MacBook-Pro d3-book-murray % http-server You should get a message that ends with something like this: Starting up http-server, serving ./ ... Available on: http://127.0.0.1:8080 http://192.168.1.54:8080 Hit CTRL-C to stop the server Copy and paste one of the URLs in the browser and you should see an index of subfolders and/or files available in the folder in which you launched the local server: From here you can navigate to the desired file. Take note that you cannot move up in the file structure so be sure to start the server in the highest level directory that you plan to access, or that the files you open need to access. In this particular case I am opening the code files for Scott Murray’s Interactive Data Visualization for the Web, 2nd ed. (available here). Rather than link to the online version of D3 as we’ve been doing, each file links to a downloaded version of D3 located in the top level directory with: <script type=\"text/javascript\" src=\"../d3.js\"></script> Therefore we must launch the local server from one level higher than the folder in which the file we wish to open resides. As indicated, Control-c in the command line will stop the server. 10.3 Other local options A simple way to avoid this issue is to upload data files to GitHub and read them from there. There are other workarounds, including opening Chrome from the command line with the --allow-file-access-from-files flag. 10.4 Hosting online An alternative to the options above are to avoid the issue by hosting your code online. Options for doing so are covering in the chapter on sharing D3 online. "],["share-d3-online.html", "11 Share D3 online 11.1 Quarto 11.2 Observable", " 11 Share D3 online There are a number of ways you can share your D3 code online. Even if you’re not sharing, there are advantages to an online setup, for example, not having to set up a local server as described in the chapter on reading files. 11.1 Quarto Separate .js file Video tutorial To include D3 in a Quarto document, I recommend putting the script in a separate .js file that is linked to both by a .qmd file in your project as well as a temporary .html file that you’ll use while creating the visualization. The rationale is that you won’t have to Quarto render your book / web site each time you update the D3 script. Create a .qmd file for the visualization Create a .qmd file with a link to the D3 library, a link to your D3 script, a <div> for adding an svg in the right place and any additional HTML needed for your visualization. Use can use this file as a template. Note that you do not need <head>, <title>, or <body> tags as these are added in the process of converting the .qmd files to HTML. Example: d3graph.qmd Create a .js file for your D3 script This file should contain your script. To ensure that the svg will appear in the book (and not below it) append the svg to the <div> in your .qmd file. Example: myscript.js Create a separate .html for development purposes Create an .html file with the same contents as your .qmd file. With this setup you can test your code without rendering the book but simply opening the .html file. Example: practice.html iframe Create your entire visualization in a separate .html file and then include in your .qmd file with <iframe>: <iframe src="mybarchart.html" width="400" height="300"></iframe> You can work on the .html file separately and view updates without rendering the book. 11.2 Observable Observable, created by D3 author Mike Bostock, is the official D3 web tool for creating and sharing D3 code. It is a powerful, popular tool–all new D3 code examples are now presented in Observable–but program flow is different than it is for stand-alone JavaScript. If you’re interested in learning more, see Why Observable. "],["line-charts.html", "12 Line charts 12.1 Lecture slides 12.2 SVG <line> element 12.3 SVG <path> element 12.4 Data for line chart 12.5 Create a line generator 12.6 Put the line generator to work 12.7 Additional Resources", " 12 Line charts Read: IDVW2, Chapter 11 Using Paths 12.1 Lecture slides line_charts.pdf 12.2 SVG <line> element (Use for two points only.) <line x1="0" y1="80" x2="100" y2="20" stroke="black" /> const x1 = 0; const y1 = 80; const x2 = 100; const y2 = 20; d3.select("svg") .append("line") .attr("x1", x1) .attr("x2", x2) .attr("y1", y1) .attr("y2", y2); 12.3 SVG <path> element (Use if you have more than two points.) <svg width = "500" height = "400"> <path d="M 50 400 L 100 300 L 150 300 L 200 33 L 250 175 L 300 275 L 350 250 L 400 125" fill="none" stroke="red" stroke-width="5"> </path> </svg> d attribute: M = move to L = line to More options: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d 12.4 Data for line chart Format that we have: Day High Temp April 1 60 April 2 43 April 3 43 April 4 56 April 5 45 April 6 62 April 7 49 Format that we need looks something like this: <path class="line" fill="none" d="M0,149.15254237288136L71.42857142857143,264.40677966101697L142.85714285714286,264.40677966101697L214.28571428571428,176.27118644067798L285.7142857142857,250.84745762711864L357.14285714285717,135.59322033898303L428.57142857142856,223.72881355932205"></path> 12.5 Create a line generator Expects data in an array of 2-dimensional arrays, that is, an array of (x,y) pairs: const dataset = [ [0, 60], [1, 43], [2, 43], [3, 56], [4, 45], [5, 62], [6, 49] ]; const mylinegen = d3.line() Test it in the Console: mylinegen(dataset); Add an ordinal scale for x: const xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .range([0, 500]) … and a linear scale for y: const yScale = d3.scaleLinear() .domain([d3.min(dataset, d => d[1]) - 20, d3.max(dataset, d => d[1]) + 20]) .range([400, 0]); *Why d[1] instead of d? (See p. 122) Add accessor functions .x() and .y(): mylinegen .x(d => xScale(d[0])) .y(d => yScale(d[1])); Test again: mylinegen(dataset); Now let’s add a <path> element with that d attribute: (this step is just for learning purposes…) const mypath = mylinegen(dataset); d3.select("svg").append("path").attr("d", mypath) .attr("fill", "none").attr("stroke", "red") .attr("stroke-width", "5"); 12.6 Put the line generator to work Now let’s do it the direct way: bind the datum and calculate the path in one step: d3.select("svg").append("path") .datum(dataset) .attr("d", mylinegen) .attr("fill", "none") .attr("stroke", "teal") .attr("stroke-width", "5"); Finally, we’ll add a class and style definitions: <style> .linestyle { fill: none; stroke: teal; stroke-width: 5px; } </style> The append(\"path\") line becomes: svg.append("path") .datum(dataset) .attr("d", mylinegen) .attr("class", "linestyle"); .linestyle { fill: none; stroke: teal; stroke-width: 5px; } Putting it all together, we have: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Line generator</title> <script src="https://d3js.org/d3.v7.js"></script> <style type ="text/css"> .linestyle { fill: none; stroke: teal; stroke-width: 5px; } </style> </head> <body> <script> const w = 500; const h = 400; const svg = d3.select("svg#noaxes"); const dataset = [ [0, 60], [1, 43], [2, 43], [3, 56], [4, 45], [5, 62], [6, 49] ]; let xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .range([0, w]); let yScale = d3.scaleLinear() .domain([d3.min(dataset, d => d[1]) - 20, d3.max(dataset, d => d[1]) + 20]) .range([h, 0]); const mylinegen = d3.line() .x(d => xScale(d[0])) .y(d => yScale(d[1])); svg.append("path") .datum(dataset) .attr("d", mylinegen) .attr("class", "linestyle"); </script> </body> </html> And another example with axes: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title></title> <script src="https://d3js.org/d3.v7.js"></script> </head> <body> <svg id="withaxes" width="600" height="400"></svg> <script> const svg2 = d3.select("svg#withaxes") const margin = {top: 20, right: 50, bottom: 30, left: 50} const width = +svg2.attr("width") - margin.left - margin.right const height = +svg2.attr("height") - margin.top - margin.bottom const g = svg2.append("g").attr("transform", `translate(${margin.left}, ${margin.top})`); const parseTime = d3.timeParse("%d-%b-%y"); xScale = d3.scaleTime().range([0, width]); yScale = d3.scaleLinear() .domain([20, 80]) .range([height, 0]); const xAxis = d3.axisBottom() .scale(xScale) .tickFormat(d3.timeFormat("%Y-%m-%d")); const line = d3.line() .x(d => xScale(d.date)) .y(d => yScale(d.high)); const data = [{"date":"1-Apr-18","high":60}, {"date":"2-Apr-18","high":43}, {"date":"3-Apr-18","high":43}, {"date":"4-Apr-18","high":56}, {"date":"5-Apr-18","high":45}, {"date":"6-Apr-18","high":62}, {"date":"7-Apr-18","high":49}]; data.forEach(function(d) { d.date = parseTime(d.date); }); xScale .domain(d3.extent(data, d => d.date)); g.append("g") .attr("transform", `translate(0, ${height})`) .call(xAxis); g.append("g") .call(d3.axisLeft(yScale)) g.append("path") .datum(data) .attr("class", "line") .attr("fill", "none") .attr("stroke", "red") .attr("stroke-width", 1.5) .attr("d", line); </script> </body> </html> (Also uses: d3.timeParse() and JavaScript Array.foreach() ) 12.7 Additional Resources Multiple Time Series in D3 by Eric Boxer (EDAV 2018) "],["layouts.html", "13 Layouts 13.1 Lecture slides 13.2 Set up data and stack method 13.3 Set up scales 13.4 Add groups 13.5 Add rectangles 13.6 Get the code", " 13 Layouts IDVW2, Chapter 13 Layouts (d3.stack() only, pp. 264-270) 13.1 Lecture slides layouts.pdf 13.2 Set up data and stack method Open the JavaScript Console // try me in the Console const w = 500; const h = 300; // original data const dataset = [ { apples: 5, oranges: 10, grapes: 22 }, { apples: 4, oranges: 12, grapes: 28 }, { apples: 2, oranges: 19, grapes: 32 }, { apples: 7, oranges: 23, grapes: 35 }, { apples: 23, oranges: 17, grapes: 43 } ]; // set up stack method const stack = d3.stack() .keys([ "apples", "oranges", "grapes" ]) .order(d3.stackOrderDescending); // data, stacked const series = stack(dataset); Try stack(dataset) in the Console. 13.3 Set up scales const xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .range([0, w]) .paddingInner(0.05); const yScale = d3.scaleLinear() .domain([0, d3.max(dataset, d => d.apples + d.oranges + d.grapes)]) .range([h, 0]); const colors = d3.scaleOrdinal(d3.schemeCategory10); Enter d3.schemeCategory10 in the Console. Now try out the colors function. What is the domain? See built-in color options here. Of course you are not limited to these and can use any appropriate color scheme. 13.4 Add groups //Create SVG element const svg = d3.select("#stacked") .append("svg") .attr("width", w) .attr("height", h); // Add a group for each row of data const groups = svg.selectAll("g") .data(series) .enter() .append("g") .style("fill", (d, i) => colors(i)); [There’s a div with id “stacked” here.] Why doesn’t anything show up yet? Right-click and Inspect to find out. 13.5 Add rectangles // Add a rect for each data value const rects = groups.selectAll("rect") .data(d => d) .enter() .append("rect") .attr("x", (d, i) => xScale(i)) .attr("y", d => yScale(d[1])) .attr("height", d => yScale(d[0]) - yScale(d[1])) .attr("width", xScale.bandwidth()); 13.6 Get the code Code for download "],["general-advice.html", "14 General Advice 14.1 Debugging Tips 14.2 Other", " 14 General Advice 14.1 Debugging Tips Make extensive use of Elements to see what’s being added to the DOM. Make extensive use of Console to check the values of variables and/or test code. Pay attention to errors in the Console. Use console.log() esp. in functions Post Minimal Working Examples on Ed Discussion in Canvas. See: “How to create a Minimal, Complete, and Verifiable example” (But don’t worry if it’s not perfect, we’re not going to judge.) Use a text editor that helps you identify unmatched () {} []. Have a tip? Click the button, add the tip, and create a pull request. 14.2 Other Save working versions! Pay attention to the order "],["solutions.html", "15 Solutions ", " 15 Solutions Web tech: shapes Solution Contributed by Tracy Liu D3 in the Console: green circles Select the circle with ID “henry” and make it blue. d3.select("svg") .select("circle#henry") .transition() // optional .duration(1000) // optional .attr("fill","blue"); Select all circles of “apple” class make them red. d3.select("svg") .selectAll("circle.apple") .attr("fill", "red"); Select the first circle and add an orange border (“stroke”), and stroke width (“stroke-width”) of 5. d3.select("svg") .select("circle") .attr("stroke", "orange") .attr("stroke-width", "5"); Select all circles of “apple” class and move them to the middle of the svg. d3.select("svg") .selectAll("circle.apple") .transition() .duration(2000) .attr("cx", d3.select("svg").attr("width") / 2) .attr("cy", d3.select("svg").attr("height") / 2); Contributed by Tracy Liu D3 in the Console: blue circles Move all the circles to the right. const svg = d3.select("svg") svg.selectAll("circle") .transition() .duration(2000) .attr("cx", 450); Move them back to the left and change their color. svg.selectAll("circle") .transition() .duration(2000) .attr("cx", 50) .attr("fill", "red"); In a text editor, add an id to the third circle in six_blue_circles.html, save the file, and then in the Console, move only that circle to the right. svg.select("circle#third") .transition() .duration(2000) .attr("cx", "450"); Move all the circles to the middle of the screen, then move them all to the same location. svg.selectAll("circle") .transition() .duration(2000) .attr("cx", 250) .transition() .duration(2000) .attr("cy", 200); (Extra: return the circles to their starting positions.) const circ = svg.selectAll("circle") .data([100, 150, 200, 250, 300, 350]); circ.transition() .duration(2000) .attr("cx", 50) .attr("cy", d => d) .attr("fill", "blue"); Contributed by Tracy Liu D3 in the Console: data bind const bluedata = [30, 20, 40, 70, 120, 70]; const circ = d3.select("svg") .selectAll("circle") .data(bluedata); circ.transition() .duration(2000) .attr("fill", "pink") .attr("r", d => d / 2) .attr("cx", d => 3 * d); Contributed by Tracy Liu Update, Enter, and Exit: horizontal bar chart For this exercise open up your text editor. We will be operating inside the <script> tags. Our goal is to create a horizontal bar chart. The first step is to create the svg element where our graph will live in. We want to make sure to make it tall and wide enough to hold the data of the given array. We also store our data in an array. const bardata = [300, 100, 150, 225, 75, 275]; const svg = d3.select("body") .append("svg") .attr("width", "700") .attr("height", "400"); Next we will bind the data to the DOM rectangles and store the selection in a variable called bars. Since there are no DOM rectangles (yet), the update and exit selections will be empty. Note that nothing will appear on the screen yet since the enter elements are not combined with DOM elements. const bars = svg.selectAll("rect") .data(bardata); Next step is to create DOM elements from the enter selection and give them the correct attributes to form a horizonal barchart. First we will set x to zero and then in order to set the y distances between the bars we will use each datapoint’s index. The mapping function for the y coordinate is (d, i) => i * 25 + 10 works as follows: When i = 0, y = 10, when i = 1, y = 35, when i = 2, y = 60, etc. Lastly, we want each rectangle’s width to be equal to its data value. bars.enter() .append("rect") .attr("x", 0) .attr("y", (d, i) => i * 25 + 10) .attr("width", d => d) .attr("height", "20") .attr("fill", "pink"); The complete solution is here Contributed by Kassie Papasotiriou Update, Enter, and Exit: merge Change the data to any six other values and update the lengths of the bars. console: const bardata = [130, 210, 90, 300, 200, 50]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(bardata); bars.transition() .duration(2000) .attr("width", d => d); Bind a new dataset, newbardata to the bars, update the bar lengths, and remove any extra bars. const newbardata = [250, 125, 80, 100]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(newbardata); bars.transition() .duration(2000) .attr("width", d => d) bars.exit() .transition() .duration(2000) .attr("width", 0) .remove(); 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. const reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(reallynewbardata); bars.transition() .duration(2000) .attr("width", d => d) bars.enter() .append("rect") .attr("width", 0) .attr("x", 30) .attr("y", (d, i) => 50 * i) .attr("height", 35) .attr("width", d => d) .attr("fill", "lightgreen") .attr("stroke", "pink") .attr("stroke-width", 5); Use .merge() to combine the update and enter selections into one selection and then transition the length of all of the bars to half their current length. const reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(reallynewbardata); bars.enter() .append("rect") .attr("x", 30) .attr("y", (d, i) => 50 * i) .attr("height", 35) .attr("width", d => d) .attr("fill", "lightgreen") .attr("stroke", "pink") .attr("stroke-width", 5) .merge(bars) .transition() .duration(2000) .attr("height", "35") .attr("width", d => d); Add text labels inside the bars at the right end with the length of the bar in pixels. const reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275]; const svg = d3.select("svg"); const bartext = svg.selectAll("text") .data(reallynewbardata); bartext.enter() .append("text") .attr("x", d => d - 5) .attr("y", (d, i) => 50 * i + 12) .text(d => d); Contributed by Tracy Liu Update, Enter, and Exit: functions Question Answers Since there are no questions we will try out a few things and explain why the bars are behaving that way. Open up the file on Chrome and type the following in you Console: By running the code below we are rebinding the new data to the DOM elements. In this case, the inital data and the new data have the same length so no new elements will be added and none will be removed. We update the data, change the fill and then change the width. update([100, 200, 300, 400, 200, 300]); By running the code below, the two data values are bound to the first two DOM elements. The color and width are changed the extra DOM elements that did not receive data values are removed. update([200, 400]); By running the code below (without refreshing the page from 2.), we bind the data, and two of the values will be in the enter selection. For those two values we create two more DOM elements, fill them with yellow and adjust their width. Next we merge all elements together and to the merge selection we readjust the widths to make sure that all elements have the correct length and we turn them to orange. Note that since in this scenario we had enter elements there will be nothing in the exit selection. update([200, 300, 200, 125]); Update, Enter, and Exit: vertical bar chart Question Answers In order to change a horizontal bar chart to a vertical barchart we need to first flip the x and y coordinates. If we only make this change we will notice that our barchart is not vertical but it is flipped (meaning that all bars seem to be upside-down). This is because the coordinate system in the svg starts from the top left and not the bottom left as we are used to. Therefore in order to bring everything “down”, we need to tweak the y coordinate. In order to do that we can subtract from the height of the svg the data value of each bar. In this way all bars will end at 400 and start d pixels before the end. // Create svg with same data const svg = d3.select("body") .append("svg") .attr("width", "500") .attr("height", "400"); const bardata = [300, 100, 150, 225, 75, 275]; const bars = svg.selectAll("rect") .data(bardata); bars.enter() .append("rect") .attr("x", (d, i) => i * 50 + 50) .attr("y", d => 400 - d) .attr("width", "35") .attr("height", d => d) .attr("fill", "lightgreen"); In addition to that, we need to reflect those changes in the update function and in addition to updating all bar’s heights we need to also update all barsnewy` coordinates. bars.enter() .append("rect") // add new elements .attr("x", (d, i) => i * 50 + 50) .attr("y", d => 400 - d) .attr("width", "35") .attr("height", d => d) .attr("fill", "yellow") .merge(bars) // merge .transition() .duration(2000) .attr("y", d => 400 - d) .attr("height", d => d) .attr("fill", "orange"); The complete solution is here Contributed by Kassie Papasotiriou Transitions: bar chart with transitions code for download rendered version "],["correlation-coefficient.html", "16 Correlation Coefficient", " 16 Correlation Coefficient h2, h3, p, text { font-family: sans-serif; text-anchor: middle; } Correlation Coefficient The correlation coefficient (r) is a measure of the linear relationship between two variables x and y. To get a sense of the connection between the appearance of points – (x,y) pairs – in a scatterplot and the value of r, click anywhere on the graph to add points. To remove points, click the Remove Points button and then mouseover points. The correlation coefficient is shown below. Add points Remove points Click on the chart below to add points. "],["spearman-rank-correlation-coefficient.html", "17 Spearman Rank Correlation Coefficient", " 17 Spearman Rank Correlation Coefficient h2, h3, p, text { font-family: sans-serif; text-anchor: middle; } .rank { fill: white; font-weight: bold; dominant-baseline: central; /* https://stackoverflow.com/questions/12250403/vertical-alignment-of-text-element-in-svg */ } #rho { font-family: serif; font-size: 18pt; } Drag the circles to reorder the rankings in Groups A & B. The correlation coefficient, \\(\\rho\\), is displayed below. \\(\\LARGE \\rho = 1 - \\frac{6 \\Sigma{d_i^2}}{n(n^2 -1)} =\\) \\(d_{i}\\) = difference between the two ranks of each observation \\(n\\) = number of observations "],["population-density.html", "18 Population Density", " 18 Population Density * { font-family: sans-serif; } .source { font-size: 9pt; } New York City Each dot represents a person. Data source: http://www.demographia.com/dm-nyc.htm Standalone version: density.html "],["weather-forecast.html", "19 Weather forecast", " 19 Weather forecast * { font-family: sans-serif; } text { font-size: 12px; } Weather forecast for Columbia University Lat, Lon: 40.807793, -73.962144 (Hover over points for more details.) Fahrenheit Celsius "],["appendix-advanced-css.html", "20 Appendix: advanced CSS 20.1 Buttons", " 20 Appendix: advanced CSS Work-in-progress 20.1 Buttons 20.1.1 .active This is a class not a pseudoclass, indicates which button(s) are pressed. 20.1.2 :active A pseudoclass. Clicking is the main way to trigger an :active state. 20.1.3 :focus A pseudoclass. Mainly used for tabbing. Clicking may focus a button but not always. A box shadow such as box-shadow: 0 0 0 3px lightskyblue; is a good choice 20.1.4 :hover As expected, can have separate hover behavior for .active buttons. 20.1.5 Example See the Pen Button .active vs :active by Joyce Robbins (https://codepen.io/jtr13) on CodePen. "],["404.html", "Page not found", " Page not found The page you requested cannot be found (perhaps it was moved or renamed). You may want to try searching to find the page's new location, or use the table of contents to find the page you are looking for. "]] +[["index.html", "D3 for R Users Welcome to D3 0.1 Workflow", " D3 for R Users Joyce Robbins 2024-11-25 Welcome to D3 rect { pointer-events: all; } .node { fill: blue; } .cursor { fill: none; stroke: brown; pointer-events: none; } .link { stroke: red; } .svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 20%; vertical-align: top; overflow: hidden; } .svg-content { display: inline-block; position: absolute; top: 0; left: 0; } Adapted from Build Your Own Graph! This guide serves as a companion text to Scott Murray’s Interactive Data Visualization for the Web, 2nd edition–henceforth IDVW2–a required text for GR5702. Be sure to get the second edition, which is a comprehensive update to D3 version 4. The first edition uses D3 version 3, which is not compatible. (The current version of D3 is actually v7. However, since differences between v4 and v5/v6/v7 are minimal, unless otherwise indicated in this guide, the code in IDVW2 will work with either.) We rely on the text heavily but also deviate from it in several ways. IDVW2 is written for graphics designers not data science students so the pain points are somewhat different. D3 is a JavaScript library, not a standalone language, so any time we refer to D3 we really mean D3/JavaScript, though it is not necessary to know JavaScript well before beginning; we will learn as we go. Most of the JavaScript we use is covered in IDVW2, though we also use some newer JavaScript options from ES5 and ES6, such as .map(), .filter(), arrow functions and template literals, that make coding easier (and more like R!)1 We use different examples, though you are strongly encouraged to study Murray’s code examples in addition to reading the text. Particularly through the first half, we don’t follow the text in order, so always refer to this guide first which will direct you to the pages of the text that you should read. This is very much a work-in-progress so please submit issues on GitHub to provide feedback and edit or add text by submitting pull requests. (Click the icon at the top of each page to get started. More detailed instructions are available on edav.info. If you would just like to view the source code, click the icon.) 0.1 Workflow A big hurdle to learning a new language is just getting setup. Often authors forget to mention what your programming environment should look like, what should be open on the screen. I will try not to do that and be as clear as possible so you know where you should be entering the code in the pages that follow. This task is somewhat complicated by the fact that we will be using a variety of workflow options. This section will serve as a reference guide; future sections will link back here as appropriate. All of our workflows require Google Chrome, so if you don’t have it already, download and install it. 0.1.1 JavaScript Console With this workflow we will open a web page–either online or local–in Chrome and run JavaScript in the Console. To view the Console, open Chrome DevTools by clicking View, Developer, JavaScript Console if you have a menu bar in Chrome, using a keyboard shortcut (Mac: option+command+j; Windows, Linux, Chrome OS: control+shift+J), or employing another one of the many options for doing so. The Console is one piece of a suite of tools available in the browser. With the DevTools open, your screen will look like this: The next chapter, Jump in the deep end, employs this workflow. 0.1.2 This book in the Console If you’re not reading the .pdf version, you can open DevTools on this very page. This is very convenient because not only to you not have to leave this book to practice D3, you can copy code blocks and paste them in the Console. In addition to opening DevTools (see above), close the side bar by clicking on the (“Toggle Sidebar”) icon on the top left of the page, to the left of the search icon, to give yourself more screen space. Let’s try it out. Open the JavaScript Console svg#demo Scroll so that both the blue rectangle above and the code chunk below are visible on your screen. Toggle the sidebar, open the Console, and then move the mouse onto the code block so the icon appears. Click on it to copy the code, paste it in the Console, and then press return. d3.select("svg#demo") .append("circle") .attr("cx", "-25") .attr("cy", "100") .attr("r", "20") .attr("fill", "red") .transition() .duration(3000) .attr("cx", "325") .remove(); Pretty neat. 0.1.3 Text editor This is a very basic local setup in which the same .html is open both in a text editor (if you don’t want to stray too far from home, use RStudio) and in a web browser (we will use Chrome), each on one half of your screen. The workflow is: make changes to the file in the text editor, save the changes and then refresh the page in the browser to see the updates. Keyboard shortcuts for saving and refreshing (on the Mac, command-s and command-r respectively) are very helpful. Let’s try an example: Download a copy of shapes.html by opening this page and clicking File, Save Page As… Open the file in a text editor of your choice on one half of your screen. On the other half of your screen open the same file in Chrome. As you make changes to the .html file, save the file and then refresh the browser to see the effects. Your screen should look like this: Ok, they’re not actually that new, but it takes a while for new JavaScript to catch on, mainly due to concern with maintaining compatibility with older browsers. Since D3 itself is not compatible with very old browsers, and since we can’t focus on everything at once, we are not going to concern ourselves with browser compatibility. If you are interested in this, caniuse.com is very helpful for looking up what works where.↩︎ "],["jump.html", "1 Quick demo 1.1 Get ready 1.2 Elements tab 1.3 Console tab 1.4 Modify elements 1.5 Add transitions 1.6 Add interactivity 1.7 Examples", " 1 Quick demo Let’s skip the explanations and start coding in D3 right now. Then we’ll go back and learn step by step. In this chapter we will work in the JavaScript Console (help). 1.1 Get ready If you don’t have it, install the Chrome browser. Download a copy of shapes.html by opening this file and choosing File, Save Page As… If Chrome is your default browser, open shapes.html by double clicking it. Otherwise, open Chrome first, click File, Open File…, and then choose shapes.html from the directory where you saved it. 1.2 Elements tab Open Chrome DevTools (help). Hover the mouse over various elements in the <body> ... </body> section. Observe the highlighted sections in the rendered web page on the left of the screen. Click on the mini black triangles to the left of the <body> and <svg> tags if needed to open these sections of the DOM tree. Your screen should look like this: Now try the reverse: right click on elements on the web page, choose “Inspect” and see what is highlighted in the Elements pane. Get comfortable with the connection between the code on the right and the rendered elements on the left. 1.3 Console tab Switch to the Console tab, next to the Elements tab. Let’s practice running some code. Note that the code is unrelated to the shapes.html web page that we have open. We will spend a lot of time in the Console since it’s interactive – think R console. Eventually we will switch to including JavaScript/D3 in .html or .js files and use the Console only for testing things out or debugging. Type the following lines of code at the prompt (>), press enter after each line–that is, after the semicolon (;)–and see what happens: 3 + 4; "3" + "4"; x = [1, 2, 3]; x[1]; x + 1; y = {a: 3, b: 4}; y["b"]; 1.4 Modify elements Now we’ll start using D3 to manipulate elements on the page. Try the following, by entering one line at a time in the Console as before: d3.select("circle").attr("cx", "200"); d3.select("circle").attr("cx", "500"); d3.select("circle").attr("cx", "100"); d3.select("circle").attr("r", "30"); d3.select("circle").attr("r", "130"); d3.select("circle").attr("r", "3"); d3.select("circle").attr("fill", "red"); d3.select("circle").attr("fill", "aliceblue"); d3.select("circle").attr("fill", "lightseagreen"); Note that “select” and “attr” are separate operations chained together with “.” – think pipe (|>) operator. Refresh the page. What happened? Go to Elements. Look at the value of the y1 attribute of the SVG <line> element. Go back to the Console and enter the following: d3.select("line").attr("y1", "10"); Switch back to Elements and observe. What happened? Stay in Elements and refresh the page. What happened to y1? Return to the Console to make style changes to the HTML elements: d3.select("h1").style("color", "purple"); d3.select("h2").style("font-size", "50px"); d3.select("h2").style("font-family", "Impact"); 1.5 Add transitions Try these: d3.select("svg").select("circle").transition().duration(2000).attr("cx", "400"); d3.select("svg").select("ellipse").transition().duration(2000).attr("transform", "translate (400, 400)"); d3.select("svg").select("line").transition().duration(2000).attr("x1", "400"); d3.select("svg").select("line").transition().duration(2000).attr("y1", "250"); d3.select("body").select("p").transition().duration(2000).style("font-size", "72px"); Experiment with more transitions. 1.6 Add interactivity Set up a function to turn the fill color to yellow: function goyellow() {d3.select(this).attr("fill", "yellow")}; Add an event listener to the circle that will be trigger a call to goyellow() on a mouseover: d3.select("svg").select("circle").on("mouseover", goyellow); Test it out. Add the same event listener to the ellipse. Test it out. Create a function goblue() that changes the fill color to blue. Add event listeners to the circle and ellipse that will trigger a call to goblue() on a mouseout. Test out your code. Try out a click event. (Note the use of an anonymous function.) d3.select("svg").select("line").on("click", function() {d3.select(this).attr("stroke-width", "10");}); Try another click event. What’s happening? d3.select("svg").on("click", function(event) {d3.select("text").text(`(${d3.pointer(event)})`)}); 1.7 Examples Check out this fun visualization by Yilan Chen (EDAV 2023) that started with shapes.html: Tricolor Dango "],["web.html", "2 Web tech 2.1 HTML 2.2 CSS 2.3 SVG 2.4 JavaScript 2.5 D3 2.6 HTML tree 2.7 Exercise : shapes", " 2 Web tech Read IDVW2, Chapter 3: Technology Fundamentals There is a lot of material in this chapter. It is worth making the effort to learn it now and start D3 with a solid foundation of elementary HTML/CSS/SVG/JavaScript. Here we examine shapes.html from Chapter 1 to see how the various technologies are combined into a single document. 2.1 HTML Note that shapes.html has an HyperText Markup Language or .html extension; HTML in fact provides the structure for the document. It has a <head> and <body> section. In the <head> section we use <script> tags to link to the D3 library: <script src="https://d3js.org/d3.v7.js"></script> HTML content is enclosed between opening an closing tags such as <h1> and </h1>. HTML class and ID attributes are included inside the opening tags: <h1 class=\"myclass\" id=\"myid\">This is an h1 header.</h1> 2.2 CSS CSS (Cascading Style Sheets) is used for styling web pages, and more importantly for our purposes, selecting elements on a page or in a graphic. We will generally work with internal style sheets since it’s simpler when starting out to have everything in one document. External style sheets, however, are generally the preferred method for web design. 2.2.1 Internal style sheet shapes.html has an internal style sheet: CSS style information appears in the <head> section marked off with <style> tags: <style type="text/css"> h1 {color:red;} /* CSS styling */ p {color:blue;} </style> Here we specify that all HTML <h1> headers should be red and all HTML paragraphs <p> should be blue. This is an example of an internal style sheet. Later we will consider alternatives: external style sheets and inline styling. Styling for coder designed classes is also specified in this section. For example, we could style a “formal” class as such: <style type="text/css"> .formal {color: red; font-size: 30px; font-family: Lucida Calligraphy; } </style> Note that classes are defined by the “.” before the name. 2.2.2 External style sheets External style sheets are .css files that contain styling information and are linked to with a <link> tag in the <head> section of an HTML document: <head> <link rel="stylesheet" href="style.css"> </head> External style sheets are the preferred way of styling as they can easily be modified without changing the web page; in fact, the motivation for CSS came from a desire in the early days of the internet to separate styling from content. Developers have the option now of choosing premade themes, which are shared through external style sheets. They can be quite complex. The .css file for the  Minty  theme from Bootswatch, for example, contains over 10,000 lines. CSS Zen Garden demonstrates the power of external style sheets: the same HTML document takes on very different looks depending on the stylesheet to which it is linked. 2.2.3 Inline styling With inline styling, styling is added to each tag individually: <span style="color: white; background-color: fuchsia; font-family: impact; font-size: 24px; border-style: solid; border-color: limegreen; border-width: 3px"> Styled inline </span> Styled inline This is how early web pages were styled. To take a step back in time, use developer tools to view the source code for the main page of www.dolekemp96.org, an old web site that has been maintained for historical purposes. As you can see, it’s a tedious way of writing content, which internal and external style sheets eliminate. Although you will not be adding inline styling manually, you will notice that when we select elements and change the styling with D3, the modifications are made inline. In other words, we do not make changes to the elements directly, not via a style sheet. 2.3 SVG SVG (Scalable Vector Graphics) is a human readable graphics format that facilitates manipulation of individual elements. You may be familiar with .svg files. Here we have SVG graphics within <svg> tags in the <body> section of the HTML document: <svg width="500" height="300"> <!-- some SVG --> <rect x="20" y="20" width="460" height="260" fill="lightblue"></rect> <circle cx="50" cy="75" r="20" fill="blue"></circle> <ellipse cx="175" cy="100" rx="45" ry="30" fill="green"></ellipse> <text x="150" y="200">(150, 200)</text> <line x1="250" y1="150" x2="300" y2="200" stroke="red" stroke-width="5"></line> </svg> (150, 200) There are very few SVG tags that you’ll need to know, and once we get going with D3, you will not have to code any SVG manually. It is worth doing a little to become familiar with the format and in particular to get used to the new location of the origin. 2.4 JavaScript JavaScript is the most common language for making web pages interactive. Code is executed when pages are opened or refreshed. So far we have run JavaScript in the Console, but have not included it in the web page itself. When we do so, it will be between <script> tags in the <body> section of the HTML document, or in a separate .js file. We will learn JavaScript on an as-needed basis. In terms of data, we will begin with simple arrays: const x = [3, 5, 1, 6, 7] In the Just Enough JS chapter, we cover more complex data structures and some methods for data manipulation. javascript.info is an excellent resource for expanding your knowledge beyond the basics. 2.5 D3 D3 (Data Driven Documents) is a JavaScript library well suited to interactive graphics. As such, it is also included between <script> tags in the <body> section. For D3 to work, you must link to the D3 library in the <head> section of the document. There seems to be a misconception that D3 is a high level language. It is not. You will be working on the pixel level to create graphics, including drawing your own axes and doing other things that you’re not used to doing if you’ve been working in R or Python. On the bright side, after D3, you will gain a new appreciation for base R graphics. You will write code such as plot(iris$Sepal.Length, iris$Sepal.Width, pch = 16, col = iris$Species, las = 1, xlab = \"Sepal.Length\", ylab = \"Sepal.Width\") and think: wow, there are axes! Amazing! It is legitimate to ask why you need to know D3 as a data scientist. Many if not most of you will not be coding in JavaScript from the ground up in your future careers. However, it’s a great way to learn how interactive graphics work under the hood, and will give you a solid foundation which you can draw on to tweak visualizations that you build with high level tools such as Plotly. 2.6 HTML tree While shapes.html appears as a single consistent document, it is actually comprised of multiple languages. HTML, CSS, and SVG are already there, and we will be adding JavaScript / D3 soon. Of note: An HTML document is composed of lines or sections set off with tags. In particular <style> ... </style>, <svg> ... </svg>, and <script> ... </script> indicate the inclusion of CSS, SVG, and JavaScript/D3 respectively. For D3 to work, you must link to a D3 library. To link to the online version, include this line: <script src=\"https://cdn.jsdelivr.net/npm/d3@7\"></script> or <script src=\"https://d3js.org/d3.v7.js\"></script>. Alternatively, you can download a copy of the library from https://d3js.org/getting-started#d3-in-vanilla-html–clicking on d3.v7.js or d3.v7.min.js will download the file. Then add the following to the <head> section of your .html file: <script src="d3.js"></script> There are two main sections. The <head> section contains the title, link to D3 library, and internal CSS. The <body> section contains HTML elements (<h1>, <p>, etc.), SVGs (between <svg>/</svg>tags) and JavaScript/D3 scripts (between <script>/<script>tags). Do not assume that if it works that it is correct; today’s browsers can be very forgiving. Comment syntax varies with language: <!-- single or multiline HTML or SVG comment --> /* single or multiline CSS comment */ // single line JavaScript comment /* JavaScript multiline comment */ 2.7 Exercise : shapes Download a copy of shapes.html by opening this page and clicking File, Save Page As… Set yourself up to work locally in a text editor help. (Developer Tools should not be open; we will not be using the Console.) Add an additional circle to the svg. Add styling to the internal style sheet to style circles. Add two additional paragraphs using the <p> tag. Add an ID attribute to one of the circles. Add a class attribute to two of the <p> tags. Use the internal style sheet to style paragraphs of the class you created in 5. Adjust additional elements as desired. Solution Contributed by Tracy Liu "],["d3console.html", "3 Modify, Add, Remove 3.1 Selections 3.2 Modify existing elements 3.3 Add elements 3.4 Remove elements 3.5 Exercise : green circles 3.6 Exercise : blue circles 3.7 Bind data… finally! 3.8 Exercise : data bind", " 3 Modify, Add, Remove Read IDVW2, Chapter 6: Drawing with Data. Skip pp. 89-96 as we will not be drawing bar charts with the divapproach. 3.1 Selections 3.1.1 Select by tag The ability to select elements on a page is key to being able to manipulate them. d3.select() will select the first match; d3.selectAll() will select all matches. d3.select("svg").select("circle"); selects the first circle in the order in which circles appear in the <svg> grouping. If there were more than one circle we could select them all with: d3.select("svg").selectAll("circle"); We can select HTML elements by tag in the same way: d3.select("body").select("h1"); d3.select("body").selectAll("h1"); 3.1.2 Select by class Classes are selected by adding a “.” before the class name: d3.select("svg").selectAll("circle.apple") This provides one method of selecting a certain collection of elements of the same type. 3.1.3 Select by ID IDs differ from classes in that they are unique identifiers. IDs are selected by adding a “#” before the ID: d3.select("svg").select("circle#henry"); 3.1.4 Store selections It is often helpful to store selections for later use. Here we store the svg selection in mysvg: const mysvg = d3.select("svg"); The JavaScript community is moving toward using let and const instead of var; we, however, will stick with var to be consistent with IDVW2. Of course you’re welcome to use const and let instead, and if so, may find these articles helpful: Let It Be - How to declare JavaScript variables and ES2015 const is not about immutability. Store circle selection in a variable: const svg = d3.select("svg"); const circ = svg.selectAll("circle"); 3.2 Modify existing elements Try out the code in this section with a downloaded copy of five_green_circles.html opened in Chrome and the Console visible. 3.2.1 Modify attributes link to get or set attribute API d3.select("circle").attr("r"); // see radius d3.select("circle").attr("r", "10"); // set radius to 10 3.2.2 Modify styles link to get or set style API d3.select("h1").style("color"); d3.select("h1").style("color", "blue"); It is often difficult to remember whether to use .attr() or .style() In general, properties such as position on the SVG, class, and ID are attributes, while decorative properties such as color, font, font size, etc. are styles. However, in some cases, you can use either. For example, the following both make the circle blue: d3.select("circle").attr("fill", "blue"); d3.select("circle").style("fill", "blue"); The first will add a fill=\"blue\" attribute to the <circle> tag, while the latter will add style=\"fill: blue;\". All is well and good until you find yourself with both in the same tag, in which case the style property will take precedence. The bottom line: don’t mix the two options because it can cause problems. To further complicate matters, .style() is just shorthand for .attr(\"style\", \"...\") so the following are in fact equivalent: d3.select("circle").style("fill", "blue"); d3.select("circle").attr("style", "fill: blue;"); In other words, style is an attribute! 3.2.3 Modify text This section is interactive: You can hover over code as directed to observe effects. The interactivity is enabled by D3 scripts that are included in the .Rmd source file of this page. If you’re interested you can view these scripts by either clicking on the eye icon above or opening Developer Tools in Chrome. In either case, look for the code between the <script> </script> tags. HTML text .fancy { color: red; font-family: garamond; font-size: 30px; } <p id="typo" class="fancy">Manhatten</p> Manhatten Hover to execute this code (and fix the typo): d3.select("#typo").text("Manhattan"); SVG text <svg width="500" height="100"> <rect width="500" height="100" fill="#326EA4"></rect> <text id="svgtypo" x="50" y="70" fill="white" font-weight="bold" font-size="40px"> Web scrapping is fun.</text> </svg> Hover on this SVG to execute the code below it (and fix the typo): Web scrapping is fun. d3.select("#svgtypo").text("Web scraping is fun."); The SVG <text> tag can be tricky. It differs from HTML text tags (<p>, <h1>, <h2>, etc.) in that it has x and y attributes that allow you to position text on an SVG canvas. Unlike HTML, the fill attribute controls the color of the text. Compare: d3.select("p").style("color", "red"); // HTML d3.select("text").attr("fill", "red"); // SVG 3.2.4 Move SVG text <svg width="600" height="100"> <rect width="600" height="100" fill="#326EA4"></rect> <text id="moveleft" x="200" y="70" fill="white" font-weight="bold" font-size="40px"> I want to move left.</text> </svg> Hover on this SVG to execute the code below it: I want to move left. d3.select("#moveleft").attr("x", "20").text("Thanks, now I'm happy!"); 3.3 Add elements 3.3.1 HTML Continue trying out code with five_green_circles.html open in Chrome. Or download the file and open it. The following adds a <p> tag but doesn’t change how the page looks, since there’s no text associated with it. d3.select("body").append("p"); To add text, use .text(): d3.select("body").append("p").text("This is a complete sentence."); To debug adding an element, go to the Elements tab to see what was added and where. If an element is in the wrong place in the HTML tree, it will not be visible. 3.3.2 SVG Likewise, here we add a <circle> to the <svg>, but we can’t see it since it has no attributes. d3.select("svg").append("circle"); Adding attributes will create visible circles: d3.select("svg").append("rect").attr("x", "0").attr("y", "0") .attr("width", "500").attr("height", "400").attr("fill", "lightblue"); d3.select("svg").append("circle").attr("cx", "200") .attr("cy", "100").attr("r", "25").attr("fill", "orange"); d3.select("svg").append("circle").attr("cx", "300") .attr("cy", "150").attr("r", "25").attr("fill", "red"); We can use a saved selection to assist in creating a new element: (IDVW2, pp. 97-98) mysvg = d3.select("svg"); mysvg.append("circle").attr("cx", "250").attr("cy", "250").attr("r", "50") .attr("fill", "red"); 3.4 Remove elements These methods will remove matching elements in order, starting with the first find in the document. 3.4.1 HTML d3.select("p").remove(); 3.4.2 SVG d3.select("svg").select("circle").remove(); d3.select("svg").selectAll("circle").remove(); 3.5 Exercise : green circles Return to five_green_circles.html, open Developer Tools, and do the following in the Console with D3: Select the circle with ID “henry” and make it blue. Select all circles of “apple” class make them red. Select the first circle and add an orange border (use attribute “stroke”), and stroke width (“stroke-width”) of 5. Select all circles of “apple” class and move them to the middle of the svg. Solution 3.6 Exercise : blue circles Return to six_blue_circles.html, open Developer Tools, and execute Steps 1-4 one at a time in the Console. After Step 4, refresh the page to go back to Step 1 if so desired. (You do not need to create a loop as in the visual.) This exercise is provided as a challenge. It’s fine to skip this exercise and move on to the next section. Move all the circles to the right. Move them back to the left and change their color. In a text editor, add an id to the third circle in six_blue_circles.html, save the file, and then in the Console, move only that circle to the right. Move all the circles to the middle of the screen, then move them all to the same location. Solution 3.7 Bind data… finally! (IDVW2, pp. 98-108) To follow along with the code in this section, download and open six_blue_circles.html. Bind data: d3.select("svg").selectAll("circle").data([90, 230, 140, 75, 180, 25]); Check data binding: d3.select("svg").selectAll("circle").data(); Set x-coordinate of each circle to data value using arrow function: d3.select("svg").selectAll("circle").attr("cx", d => d); Set x-coordinate of each circle to data value with a JavaScript function: d3.select("svg").selectAll("circle").attr("cx", function(d) {return d;}); We’ll bind a new set of data to the circles, this time storing the dataset in a variable: const dataset = [50, 80, 110, 140, 170, 200]; We’ll also store a selection of all circles before binding the data: const circ = d3.select("svg").selectAll("circle"); And now, the data bind: circ.data(dataset); Nothing appears to have happened; the circles remain the same and there is no evidence of any changes looking at the circles in the DOM (see Elements tab). We can check that the data are indeed bound with: circ.data(); // now we see data Modify elements w/ stored selections, bound data: circ.attr("cx", function(d) {return d;}); circ.attr("cx", function(d) {return d/2;}); circ.attr("cx", function(d) {return d/4;}).attr("r", "10"); Same as above, using arrow functions: circ.attr("cx", d => d); circ.attr("cx", d => d/2); circ.attr("cx", d => d/4).attr("r", "10"); Note that if we bind a new set of data to the DOM elements, the original set will be overwritten: const newdata = [145, 29, 53, 196, 200, 12]; circ.data(newdata); circ.transition() .duration(2000) .attr("cx", d => 2*d); 3.8 Exercise : data bind Return to six_blue_circles.html, open Developer Tools, and practice binding data to the circles and modifying the circles based on the data as in the examples above. "],["update-enter-and-exit.html", "4 Update, Enter, and Exit 4.1 Lecture slides 4.2 Use exit selection to remove elements 4.3 Use enter selection to add elements 4.4 Data / enter / append sequence 4.5 Exercise : horizontal bar chart 4.6 Merge selections 4.7 Exercise : merge 4.8 Groups 4.9 General Update Pattern (with merge) 4.10 General Update Pattern (with join) 4.11 Exercise: : functions 4.12 Exercise : vertical bar chart", " 4 Update, Enter, and Exit Read: IDVW2, Chapter 9, pp. 178-184; Chapter 12, pp. 231-249 4.1 Lecture slides D3 Data Bind Jump to data/enter/append Jump to general update pattern 4.2 Use exit selection to remove elements a.k.a. more DOM elements than data values We’ll start with six circles and remove some. Open six_blue_circles.html in Chrome and open the JavaScript Console. Let’s bind four data values to the six circles: d3.select("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: const circ = d3.select("svg") .selectAll("circle") .data([123, 52, 232, 90]); Let’s look at the exit selection: circ.exit(); Try this: circ.attr("fill", "red"); What happened and why? Now try this: circ.exit().attr("fill", "purple"); What happened and why? What do you think this will do? Try it. circ.exit().transition().duration(2000).remove(); Create a new variable circ2 and compare it to circ: const circ2 = d3.selectAll("circle"); circ.data(); circ2.data(); circ.exit(); circ2.exit(); What’s going on? 4.3 Use enter selection to add elements a.k.a. more data values than DOM elements We’ll start with six_blue_circles.html in Chrome and add some circles. First, let’s bind new data to the circles: const circ = d3.select("svg") .selectAll("circle") .data([123, 52, 232, 90, 34, 12, 189, 110]); And look at the enter selection: circ.enter(); How many placeholders are in the enter selection? Let’s add circles for each of these placeholders: circ.enter() .append("circle") .attr("cx", "100") .attr("cy", (d, i) => i * 50 + 25) .attr("r", "20") .attr("fill", "blue"); Try this: circ.transition() .duration(3000) .attr("cx", "400"); What do you need to do to act on all of the circles? d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cy", (d, i) => (i * 50) + 25) .attr("cx", "200"); 4.4 Data / enter / append sequence We’ll start with nothing–not even an SVG–and add elements with the data / enter / append sequence. Work in the Console on this page (help). Open the JavaScript Console The SVG will be added here: d3.select("div#dea") .append("svg") .attr("width", "400") .attr("height", "250"); Create an array of values: const specialdata = [75, 150, 200]; Add rectangles: d3.select("svg") .selectAll("rect") .data(specialdata) .enter() .append("rect") .attr("x", d => d) .attr("y", d => d) .attr("width", "50") .attr("height", "30") .attr("fill", "pink"); 4.4.1 Labels Note that we can also label the rectangles with the data value: d3.select("svg") .selectAll("text") .data(specialdata) .enter() .append("text") .attr("x", d => d + 25) .attr("y", d => d + 25) .text(d => d) .attr("fill", "blue") .attr("text-anchor", "middle"); 4.5 Exercise : horizontal bar chart Save a copy of this exercise and open it in your text editor. Create a horizontal bar chart with bar widths equal to the data values stored in bardata. Do so by replacing all the “ADD’s” with constants or functions and then uncommenting those lines. const bardata = [300, 100, 150, 225, 75, 275]; It should look like this: Solution 4.6 Merge selections We now know how to work separately with the update, enter, and exit selections. Often in practice we wish to do the same thing or almost the same thing with the enter and update selections. That is where .merge() comes in. If we merge the update and enter selections we don’t have to repeat our code. Open six_blue_circles.html in Chrome. Run the following code in the Console: const newdata = [123, 52, 232, 90, 34, 12, 189, 110]; const svg = d3.select("svg"); const circ = svg.selectAll("circle") .data(newdata); circ.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) .transition() .duration(2000) .attr("cx", "200"); Note the pattern: Create a data array Store the svg selection Store the data bind in X X.enter() .append(some shape) *add attributes* // acts on enter selection only (no transitions!) .merge(X) *attributes, other stuff* // acts on enter and update selections Do not include transitions in a stored selection! 4.7 Exercise : merge Open this bar chart in Chrome and work in the Console. (You don’t have to download it.) All of your solutions should begin with: Creating a data array (ex. const dataset = [1, 2, 3];) Selecting the svg and storing it (const svg = d3.select(\"svg\");) Binding the data and storing it (ex. const bars = svg.selectAll(\"rect\").data(dataset));) Change the data to any six other values and update the lengths of the bars. Bind a new dataset, newbardata to the bars, update the bar lengths, and remove any extra bars. newbardata = [250, 125, 80, 100]; 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]; 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. Add text labels inside the bars at the right end with the length of the bar in pixels. Solution 4.8 Groups Open six_blue_circles.html in Chrome. Run this code in the Console: const specialdata = [100, 250, 300]; const bars = d3.select("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: const svg = d3.select("svg"); const specialdata = [100, 250, 300]; const bars = d3.select("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: d3.select("svg") .select("g#rects") .selectAll("rect") .attr("fill", "purple"); and d3.select("svg") .selectAll("rect") .attr("fill", "purple"); 4.9 General Update Pattern (with merge) Open Developer Tools on this page. Create a function in the Console: function changedata(data) { d3.select("svg#gup") .selectAll("rect") .data(data) .attr("width", d => d); } Test it out: changedata([258, 373, 278, 9, 72, 96]); What happens if there are too many data values? changedata([196, 360, 283, 390, 46, 56, 152]); Let’s use the enter selection to add new bars in this case: function changedata(data) { const bars = d3.select("svg#gup") .selectAll("rect") .data(data); // bars is the update selection bars.enter() .append("rect") .attr("x", "30") // until merge, acts on .attr("y", (d, i) => i * 50) // enter selection only .attr("height", "35") .attr("fill", "lightgreen") .merge(bars) // merge in the update selection .attr("width", d => d); // acts on all bars } What happens if we have more bars than data values? changedata([325, 116, 25]); Let’s add to the function to remove the extra bars in this case: function changedata(data) { const bars = d3.select("svg#gup") .selectAll("rect") .data(data); // bars is the update selection bars.enter() .append("rect") .attr("x", "30") // until merge, acts on .attr("y", (d, i) => i * 50) // enter selection only .attr("height", "35") .attr("fill", "lightgreen") .merge(bars) // merge in the update selection .attr("width", d => d); // acts on all bars bars.exit() .remove(); } Try: changedata([271, 49, 389]); VOILA! We have created the D3 General Update Pattern! It is covered in IDVW in the “Other Kinds of Data Updates” section on pp. 178-186 in Chapter 9. (The earlier part of Chapter 9 deals with data updates in which the number of DOM elements remains the same.) Note that the General Update Pattern changed with D3 Version 4 so avoid examples from Version 3. Also available here for download: general_update_pattern.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <script id="s1"> // Create svg and initial bars const svg = d3.select("body") .append("svg") .attr("width", "500") .attr("height", "400"); const bardata = [300, 100, 150, 225, 75, 275]; const bars = svg.selectAll("rect") .data(bardata); bars.enter().append("rect") .attr("x", "30") .attr("y", (d, i) => i*50) .attr("width", d => d) .attr("height", "35") .attr("fill", "lightgreen"); // General Update Pattern function update(data) { const bars = svg.selectAll("rect") // data join .data(data); bars.enter() .append("rect") // add new elements .attr("x", "30") .attr("y", (d, i) => i*50) .attr("width", d => d) .attr("height", "35") .attr("fill", "yellow") .merge(bars) // merge .transition() .duration(2000) .attr("width", d => d) .attr("fill", "orange"); bars.exit().remove(); // remove extra elements } </script> </body> </html> 4.10 General Update Pattern (with join) Optional This is a newer method–introduced in v5–which simplifies the general update pattern by automatically adding elements for the enter selection, removing elements for the exit selection, merging the enter and update selections and then acting on them all with .join(). The update pattern above could be replaced with the following: function changedata2(data) { const svg = d3.select("svg#gup") svg.selectAll("rect") .data(data) .join("rect") // need "rect" for appending elements .attr("x", "30") .attr("y", (d, i) => i * 50) .attr("height", "35") .attr("fill", "lightgreen") .attr("width", d => d); } Try: changedata2([271, 49, 389]); With .join() you can get more granular with enter, update, and exit selections as we did previously. changedata3() is equivalent to changedata2(): function changedata3(data) { const svg = d3.select("svg#gup") svg.selectAll("rect") .data(data) .join( enter => enter.append("rect") .attr("x", "30") .attr("y", (d, i) => i * 50) .attr("height", "35") .attr("width", d => d) .attr("fill", "lightgreen"), update => update .attr("width", d => d), exit => exit.remove() ); } Generally, however, unless you have transitions, you will not need to control the enter, exit and update selections separately. 4.11 Exercise: : functions Open general_update_pattern.html and practice running the update() function with different datasets in the Console. For example: update([100, 200, 300]); Solution 4.12 Exercise : vertical bar chart Save a copy of this exercise and open it in your text editor. Create a vertical bar chart with bar heights equal to the data values stored in bardata. Do so by replacing all the “ADD’s” with constants or functions and then uncommenting those lines. Solution "],["just-enough-js.html", "5 Just Enough JS 5.1 Arrays of arrays 5.2 Arrays of objects 5.3 .map() 5.4 D3 sorting 5.5 D3 statistics 5.6 D3 + .map()", " 5 Just Enough JS Basics: IDVW, pp. 36-52 Before JavaScript ES6, the ‘var’ keyword was used to declare a variable. Variables declared using the ‘var’ keyword are either globally or functionally scoped, they do not support block-level scope. Therefore, in JavaScript ES6, the ‘let’ keyword and ‘const’ keyword were introduced. The ‘let’ keyword deals with a block scope. It can be reassigned but cannot be redeclared. The ‘const’ keyword is also blocked scoped. It cannot be reassigned and cannot be redeclared. As a general rule, you should always declare variables with ‘const’, if you realize that the value of the variable needs to change, go back and change it to ‘let’. For more detailed information regaring ‘var’, ‘let’ and ‘const’, please see Difference between var, let, and const keyword in JavaScript objects, arrays, arrays of objects, functions (and other things) 5.1 Arrays of arrays Open the JavaScript Console // try me in the Console const array_dataset = [[100, 75, 30], [200, 125, 20]]; d3.select("svg#arrays") .selectAll("circle") .data(array_dataset) .enter() .append("circle") .attr("cx", d => d[0]) .attr("cy", d => d[1]) .attr("r", d => d[2]) .attr("fill", "red"); svg#arrays 5.2 Arrays of objects // Try me in the Console const object_dataset = [ {cx: 100, cy: 150, fill: `red`}, {cx: 200, cy: 100, fill: `blue`} ]; d3.select("svg#objects") .selectAll("circle") .data(object_dataset) .enter() .append("circle") .attr("cx", d => d.cx) .attr("cy", d => d.cy) .attr("r", "30") .attr("fill", d => d.fill); svg#objects See also: JavaScript Array of Objects Tutorial 5.3 .map() What’s the issue? In R many operations are vectorized: sqrt(3) ## R output ## [1] 1.732051 x <- c(3, 5, 7) sqrt(x) ## R output ## [1] 1.732051 2.236068 2.645751 Not so in JavaScript: Math.sqrt(3); // Try me in the Console const x = [3, 5, 7]; // Try me in the Console Math.sqrt(x); // Doesn't work... 5.3.1 Simple arrays Use .map() to operate on each array element separately. The concept is similar to lapply() or purrr::map(), but unlike in R, it’s needed for simple arrays. R x <- c(3, 5, 7) sqrt(x) ## R output ## [1] 1.732051 2.236068 2.645751 JavaScript Do something to every element of a simple array: // take the square root of each element const x = [3, 5, 7]; // try me x.map(Math.sqrt); // multiply each element by 3 [4, 10, 12].map(d => d*3); // try me // multiply each element by 3 [4, 10, 12].map(function(d) {return d*3;}); // try me // multiply each element by its index [10, 20, 30, 40].map((d, i) => d*i); // try me R: Sum two arrays # sum two arrays x <- 1:3 y <- 4:6 x + y ## R output ## [1] 5 7 9 JavaScript: Sum two arrays // sum two arrays const x = [1, 2, 3]; const y = [4, 5, 6]; x + y // try me... what went wrong? // sum two arrays const x = [1, 2, 3]; const y = [4, 5, 6]; x.map((d, i) => d + y[i]); // try me 5.3.2 Arrays of arrays Do something to the first item of every element of a nested array: [[1, 2], [3, 4]].map(d => Math.sqrt(d[0])) // try me Sum up all items in each element of the array: [[1, 2, 3], [4, 5, 6]].map(d => d[0] + d[1] + d[2]); // try me Created a nested array out of a simple array: [10, 20, 30].map(d => [d, Math.pow(d, 2)]); 5.3.3 Create arrays of objects Create an array of objects out of a simple array (note the parentheses around the object): [10, 20, 30].map(d => ({n: d, nsq: Math.pow(d, 2)})); // try me [10, 20, 30].map((d, i) => ({index: i, value: d})); // try me 5.4 D3 sorting Use d3.sort() rather than plain JavaScript options. const y = [3, 1, 5, 12, 7]; // try me d3.sort(y); 5.5 D3 statistics link to API D3 brings us back to familiar ground with functions that take an array and return a single value. Here are D3 functions with the same names and behavior as their R equivalents: R D3 min(x) d3.min(x) max(x) d3.max(x) sum(x) d3.sum(x) mean(x) d3.mean(x) median(x) d3.median(x) A few with different names: R D3 range(x) d3.extent(x) var(x) d3.variance(x) sd(x) d3.deviation(x) d3.quantile() takes a single value for p, not an array as in R. (In earlier versions of D3 it was necessary to sort the array before finding quantiles, but this is no longer the case.) R D3 quantile(x) d3.quantile(x, p) Thus for a single quantile we have: const x = [12, 34, 1, 43, 90, 72]; // try me d3.quantile(x, .25); https://github.com/d3/d3/blob/main/API.md#statistics 5.6 D3 + .map() D3 statistics functions combined with .map() can be helpful in a variety of situations. Vectorizing a parameter, for example to mimic quantile(x) in R: R x <- c(1, 12, 34, 43, 72, 90); quantile(x) ## R output ## 0% 25% 50% 75% 100% ## R output ## 1.00 17.50 38.50 64.75 90.00 JavaScript const x = [1, 12, 34, 43, 72, 90]; // try me [0, .25, .5, .75, 1].map(p => d3.quantile(x, p)); Sum up the first item of all elements in an array of arrays: R l <- list(c(100, 200, 40), c(300, 150, 20)) sum(purrr::map_dbl(l, ~.x[1])) ## R output ## [1] 400 JavaScript const dataset = [[100, 200, 40], [300, 150, 20]]; // try me d3.sum(dataset.map(d => d[0])); Sum up all items in each array to create a simple array: R l <- list(c(100, 200, 40), c(300, 150, 20)) purrr::map_dbl(l, ~sum(.x)) ## R output ## [1] 340 470 JavaScript const dataset = [[100, 200, 40], [300, 150, 20]]; // try me dataset.map(d => d3.sum(d)); "],["scales-and-axes.html", "6 Scales and Axes 6.1 Scales 6.2 Margins 6.3 Axes 6.4 Bar chart with categorical labels", " 6 Scales and Axes 6.1 Scales 6.1.1 Lecture slides Scales 6.1.2 Practice See: IDVW2, Chapter 7: Scales Practice creating an ordinal scale in the Console: Open the JavaScript Console const myscale = d3.scaleBand() .domain([0, 1, 2, 3, 4]) .range([0, 100]); myscale(1); Try other numbers: myscale(3);, myscale(2.5);, myscale(7);, etc. Add inner padding and try again. More on band scales here: https://d3js.org/d3-scale/band *Be sure to use d3.scaleBand(), not d3.scaleOrdinal() for this use case. 6.1.3 Exercise : vertical bar chart d3.scaleBand() IDVW2 Chapter 9, pp. 150-153 Create the vertical bar chart shown below by filling in the lines marked ADD in this file and uncommenting them. (Note that we are not yet employing a linear scale for the y-axis.) Solution d3.scaleLinear() In the next graph, d3.scaleLinear() is added to create a yScale function to convert bar heights to pixels. Change the data and observe how the bars are resized to fit on the SVG. Code for download 6.2 Margins 6.2.1 Lecture slides Margins “Margin convention” const w = 500; const h = 400; const margin = {top: 25, right: 0, bottom: 25, left: 25}; const innerWidth = w - margin.left - margin.right; const innerHeight = h - margin.top - margin.bottom; 6.2.2 Bar chart with margins Code for download 6.3 Axes See: IDVW2, Chapter 8: Axes 6.3.1 Lecture slides Axes 6.3.2 Bar chart with axes Code for download Practice changing the data and seeing what happens. 6.4 Bar chart with categorical labels Code for download "],["interactivity.html", "7 Interactivity 7.1 Binding event listeners to SVG elements 7.2 Separating the function and event listener 7.3 HTML buttons 7.4 Radio buttons 7.5 Dependent event listeners", " 7 Interactivity Read: IDVW2, Chapter 10 Interactivity 7.1 Binding event listeners to SVG elements (100, 150) It’s helpful to think carefully about what you want to happen when an event listener is triggered and what information you need. Open Developer Tools and try these in the Console. Note that event management changed in v6 so code written for earlier versions of D3 will not work. 7.1.1 Do something unrelated to the element that received the event d3.select("svg") .on("click", function () { d3.select("svg") .append("text") .attr("x", "100") .attr("y", "40") .text("Hello World"); }); 7.1.2 Change an attribute of the element that received the event d3.select("line") .on("click", function() { d3.select(this) .attr("stroke-width", "10"); }); In the context of event handlers, “this” is the element that received the event, a.k.a. what you clicked on if it’s a click event. An alternative (\\(\\geq\\) v6, see link above) is to pass the event and access the element with event.currentTarget: or d3.select("line") .on("click", function(event) { d3.select(event.currentTarget) .attr("stroke", "yellow"); }); 7.1.3 Get the value of an attribute of the element that received the event d3.select("circle") .on("click", function(event) { const rad = d3.select(event.currentTarget).attr("r"); d3.select("text") .text(`The radius is ${rad} pixels.`); }); 7.1.4 Do something with the data bound to the element that received the event d3.select("circle") .data([{s: "red", sw: "15"}]) .on("click", function(event, d) { d3.select(event.currentTarget) .attr("stroke", d.s) .attr("stroke-width", d.sw); }); Note that starting with v6, the data is the 2nd parameter to be passed: function(event, d). In addition, note that you do not need to pass d again when accessing the data: for example we use d.s not d => d.s. As in the previous example, d3.select(this) can be used instead of d3.select(event.currentTarget). Try changing the data value bound to the circle with d3.select(\"circle\").datum(\"10\") and clicking again. 7.1.5 Get the svg location of the event d3.select("svg") .on("click", function(event) { d3.select("text") .text(`(${d3.pointer(event).map(Math.round)})`) }); (Up to v5, d3.mouse(this) was used instead of d3.pointer(event).) 7.2 Separating the function and event listener Examples function goyellow() { d3.select(this) .attr("fill", "yellow") }; d3.select("circle") .on("mouseover", goyellow); 7.3 HTML buttons <button type="button" onclick="showdate()">Click for date</button> function showdate() { console.log(Date()); } Click for date 7.3.1 Exercise Add buttons as indicated to this file. 7.4 Radio buttons HTML: <p id="color" style="background-color: silver; color: white;"> Please select your favorite primary color:</p> <input type="radio" name="fav_color" value="red">red</input> <input type="radio" name="fav_color" value="blue">blue</input> <input type="radio" name="fav_color" value="yellow">yellow</input> Note: type is always radio for radio buttons name is shared for a group of radio buttons value is unique JavaScript: d3.selectAll('input[name="fav_color"]') .on("click", function(event) { var favcolor = event.currentTarget.value; d3.select("p#color").style("color", favcolor); }); Please select your favorite primary color: red blue yellow 7.5 Dependent event listeners In these examples, the behavior or existence of one event listener depends on another. 7.5.1 Global variable example Here the circle click behavior depends on the value of the radio button: if the “Move left” radio button is checked, the circle will move left when clicked. If the “Move right” radio button is checked, the circle will move right when clicked. A global variable is used to keep track of the radio button value. The event listener on the circle conditions the behavior on the value of this global variable. Click the circle.  Move left  Move right svg#radio // global variable keeps track of which radio button is clicked let action = "left"; d3.select("div#rad") .selectAll("input") .on("click", function() { action = d3.select(this).node().value; }); // circle click behavior depends on value of "action" d3.select("svg#radio").select("circle") .on("click", function () { let cx_new; if (action == "left") { cx_new = +d3.select(this).attr("cx") - 50; if (cx_new < 20) cx_new = 20; } else { cx_new = +d3.select(this).attr("cx") + 50; if (cx_new > 280) cx_new = 280; } d3.select(this) .transition() .duration(500) .attr("cx", cx_new); }); 7.5.2 Turn off event listener In this example, the event listeners on the squares are turned on or off depending on the value of the radio button. Event listeners can be removed by setting the behavior to null. Click a square.  Red active  Blue active svg#radio2 // movement function const jump = function () { d3.select(this).transition().duration(500) .attr('y', '0') .transition().duration(500).ease(d3.easeBounce) .attr('y', '75'); }; // initial setup: add event listener to red square d3.select("svg#radio2") .select("rect#red") .on("click", jump); // switch event listeners if radio button is clicked d3.select("div#rad2").selectAll("input") .on("click", function () { if (d3.select(this).node().value == "blue") { d3.select("svg#radio2").select("rect#blue").on("click", jump); d3.select("svg#radio2").select("rect#red").on("click", null); } else { d3.select("svg#radio2").select("rect#red").on("click", jump); d3.select("svg#radio2").select("rect#blue").on("click", null); } }); "],["transitions.html", "8 Transitions 8.1 Examples 8.2 Do this 8.3 Not this 8.4 Strategy 8.5 Exercise : Bar chart with transitions", " 8 Transitions Read IDVW2, Chapter 9: transitions section (pp. 158-178) 8.1 Examples Open Developer Tools and try in the Console: d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cx", "275"); d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cx", "25") .attr("fill", "green"); 8.2 Do this Run simultaneous transitions on different selections: d3.select("svg").selectAll("circle#henry").transition() .duration(2000).attr("cx", "275"); d3.select("svg").selectAll("circle.apple").transition() .duration(2000).attr("cx", "25"); Run sequential transitions on the same selection in one chain: d3.select("svg").selectAll("circle") .transition().duration(2000).attr("cx", "275") .transition().duration(2000).attr("cx", "25"); Transition from something to something: d3.select("svg").append("circle") .attr("cx", "200") .attr("cy", "100") .attr("r", "5") .attr("fill", "lightblue") .transition() .duration(4000) .attr("r", "25") .attr("fill", "blue"); 8.3 Not this DO NOT run two transitions on the same selection at the same time (see p. 172). (What works in the Console will not work in a script.) d3.select("svg").selectAll("circle").transition() .duration(2000).attr("cx", "250"); d3.select("svg").selectAll("circle").transition() .duration(2000).attr("cx", "75"); DO NOT transition from nothing to something: d3.select("svg").append("circle") .transition() .duration(2000) .attr("cx", "200") .attr("cy", "100") .attr("r", "25") .attr("fill", "red"); DO NOT store a selection with a transition (it’s no longer a selection with the transition): Try this: const circ = d3.select("svg") .selectAll("circle") .data([50, 95, 100, 200, 50, 150, 250]) .enter() .append("circle") .attr("cx", d => d) .attr("cy", "100") .attr("fill", "blue") .attr("r", "0") .transition() .duration(2000) .attr("r", "25"); And then this: circ.attr("fill", "green"); DO NOT put a transition before a merge: d3.select("svg") .selectAll("circle") .transition() .duration(2000) .attr("cx", "300") .merge("oldcirc") .attr("fill", "green"); BE AWARE that not everything transitions (for example, text doesn’t.) 8.4 Strategy Example 1 Think carefully about what you want to happen, and then decide what goes before and after the transition. Add bar Remove bar Plan what you want to happen: new bars appear on the right side with orange fill new bars slide into place from the right as old bars are repositioned new bars transition to blue removed bars transition to right before disappearing 8.5 Exercise : Bar chart with transitions Download and make changes to bar_transition.html in a text editor so the transitions work as shown below. Solution code for download rendered version Further reading: Working with Transitions. "],["object.html", "9 Object Constancy 9.1 Lecture slides 9.2 No object constancy 9.3 Object constancy", " 9 Object Constancy 9.1 Lecture slides object_constancy.pdf 9.2 No object constancy Transitions  Off  On Add bar Remove bar (right) Remove bar (left) Of note: Rather than smoothly transitioning off to the left, all bars are resized when “Remove bar (left)” is clicked When \"Remove bar (right) is clicked, the bar on the right immediately disappears, and then the remaining bars transition to their new places to the right. Standalone version: no_object_constancy.html 9.3 Object constancy Transitions  Off  On Add bar Remove bar (right) Remove bar (left) Of note: Bars now smoothly transition off to the left and right Standalone version: object_constancy.html 9.3.1 Practice joining data by key Open the JavaScript Console Try the following: Create an svg with four text elements: const dataset = [{key: 12, x: 163, y: 200}, {key: 14, x: 206, y: 304}, {key: 16, x: 452, y: 152}, {key: 18, x: 321, y: 254}]; const svg = d3.select("#key").append("svg") .attr("width", "600").attr("height", "400"); svg.append("rect").attr("width", "600") .attr("height", "400").attr("fill", "aliceblue"); svg.selectAll("text") .data(dataset, d => d.key) .enter() .append("text") .attr("x", d => d.x) .attr("y", d => d.y) .text(d => `key: ${d.key}`); Bind a new dataset by key: const svg = d3.select("#key").select("svg"); const dataset = [{key: 12, x: 100, y: 200}, {key: 16, x: 250, y: 300}]; svg.selectAll("text") .data(dataset, d => d.key) .exit() .remove(); Then: svg.selectAll("text") .attr("x", d => d.x) .attr("y", d => d.y); And another one: const svg = d3.select("#key").select("svg"); const dataset = [{key: 23, x: 300, y: 150}, {key: 5, x: 450, y: 270}, {key: 16, x: 200, y: 250}]; const databind = svg.selectAll("text") .data(dataset, d => d.key); databind .enter() .append("text") .merge(databind) .attr("x", d => d.x) .attr("y", d => d.y) .text(d => `key: ${d.key}`); databind.exit().remove(); Experiment with other data binds. "],["reading-files.html", "10 Reading files 10.1 Promises 10.2 Local server 10.3 Other local options 10.4 Hosting online", " 10 Reading files As you’ve surely noticed by this point, many things in JavaScript operate on an asynchronous basis. Code is not executed linearly from beginning to end but rather in response to various triggers. For example, event listeners behave asynchronously: code will execute only if a mouse click event occurs. The benefit to reading files asynchronously is that we don’t have to wait to while a file loads for other things to happen. It would be very frustrating to navigate to a new web page and have to wait for all the scripts to finish before we could do anything on the page. 10.1 Promises Loading data is one area where D3 v5 introduces major changes from D3 v4. While v4 uses callbacks, v5 switches to promises, as promises facilitate cleaner and more flexile code than callbacks. The concept is simple. We want to control what code needs to wait until data loaded to be executed and what doesn’t. We can do that with the following structure: const rowConverter = function (d) { return { disp: +d.disp, mpg: +d.mpg, carname: d.carname, cylcolor: d.cylcolor } }; d3.csv("https://raw.githubusercontent.com/jtr13/d3book/main/data/mtcars.csv", rowConverter) .then(function(data) { // stuff that requires the loaded data }) .catch(function(error) { // error handling }); The row converter function is used to select variables and change data types (“+” converts to floating point). d3.csv() returns a promise. If the promise is resolved, the .then() function will execute; if the promise is rejected, the .catch() function will execute. Forget the mindset that you read files and store them in variables for later use. It doesn’t work that way here. The data is read in and acted on immediately. If most of the code requires loaded data, then most of the code will appear in the .then() method. A simple example of loading data in v5 can be found in this block. In contrast to the example above, an anonymous row converter function (with arrow functions) is used instead of calling a separate row converter function. Note as well that it’s not necessary to include all variables in the row converter as this author has done. For example, you could delete all the variables that aren’t used, so that the row converter in the d3.csv line becomes: d => ({ HighwayMpg: parseInt(d.HighwayMpg), Horsepower: parseInt(d.Horsepower), }) You will see that the code still works. For more about d3.csv(), see the d3.fetch API. 10.2 Local server Note: As long as you read from online sources as in the example above, you do not need to set up a local server. For security reasons, Chrome does not let you read local files. To be able to do so, you can run a local server. One option is http-server. Follow the instructions to install http-server, navigate in a terminal to the directory with your html file, and then enter http-server: joycerobbins@MacBook-Pro d3-book-murray % http-server You should get a message that ends with something like this: Starting up http-server, serving ./ ... Available on: http://127.0.0.1:8080 http://192.168.1.54:8080 Hit CTRL-C to stop the server Copy and paste one of the URLs in the browser and you should see an index of subfolders and/or files available in the folder in which you launched the local server: From here you can navigate to the desired file. Take note that you cannot move up in the file structure so be sure to start the server in the highest level directory that you plan to access, or that the files you open need to access. In this particular case I am opening the code files for Scott Murray’s Interactive Data Visualization for the Web, 2nd ed. (available here). Rather than link to the online version of D3 as we’ve been doing, each file links to a downloaded version of D3 located in the top level directory with: <script type=\"text/javascript\" src=\"../d3.js\"></script> Therefore we must launch the local server from one level higher than the folder in which the file we wish to open resides. As indicated, Control-c in the command line will stop the server. 10.3 Other local options A simple way to avoid this issue is to upload data files to GitHub and read them from there. There are other workarounds, including opening Chrome from the command line with the --allow-file-access-from-files flag. 10.4 Hosting online An alternative to the options above are to avoid the issue by hosting your code online. Options for doing so are covering in the chapter on sharing D3 online. "],["share-d3-online.html", "11 Share D3 online 11.1 Quarto 11.2 Observable", " 11 Share D3 online There are a number of ways you can share your D3 code online. Even if you’re not sharing, there are advantages to an online setup, for example, not having to set up a local server as described in the chapter on reading files. 11.1 Quarto Separate .js file Video tutorial To include D3 in a Quarto document, I recommend putting the script in a separate .js file that is linked to both by a .qmd file in your project as well as a temporary .html file that you’ll use while creating the visualization. The rationale is that you won’t have to Quarto render your book / web site each time you update the D3 script. Create a .qmd file for the visualization Create a .qmd file with a link to the D3 library, a link to your D3 script, a <div> for adding an svg in the right place and any additional HTML needed for your visualization. Use can use this file as a template. Note that you do not need <head>, <title>, or <body> tags as these are added in the process of converting the .qmd files to HTML. Example: d3graph.qmd Create a .js file for your D3 script This file should contain your script. To ensure that the svg will appear in the book (and not below it) append the svg to the <div> in your .qmd file. Example: myscript.js Create a separate .html for development purposes Create an .html file with the same contents as your .qmd file. With this setup you can test your code without rendering the book but simply opening the .html file. Example: practice.html iframe Create your entire visualization in a separate .html file and then include in your .qmd file with <iframe>: <iframe src="mybarchart.html" width="400" height="300"></iframe> You can work on the .html file separately and view updates without rendering the book. 11.2 Observable Observable, created by D3 author Mike Bostock, is the official D3 web tool for creating and sharing D3 code. It is a powerful, popular tool–all new D3 code examples are now presented in Observable–but program flow is different than it is for stand-alone JavaScript. If you’re interested in learning more, see Why Observable. "],["line-charts.html", "12 Line charts 12.1 Lecture slides 12.2 SVG <line> element 12.3 SVG <path> element 12.4 Data for line chart 12.5 Create a line generator 12.6 Put the line generator to work 12.7 Additional Resources", " 12 Line charts Read: IDVW2, Chapter 11 Using Paths 12.1 Lecture slides line_charts.pdf 12.2 SVG <line> element (Use for two points only.) <line x1="0" y1="80" x2="100" y2="20" stroke="black" /> const x1 = 0; const y1 = 80; const x2 = 100; const y2 = 20; d3.select("svg") .append("line") .attr("x1", x1) .attr("x2", x2) .attr("y1", y1) .attr("y2", y2); 12.3 SVG <path> element (Use if you have more than two points.) <svg width = "500" height = "400"> <path d="M 50 400 L 100 300 L 150 300 L 200 33 L 250 175 L 300 275 L 350 250 L 400 125" fill="none" stroke="red" stroke-width="5"> </path> </svg> d attribute: M = move to L = line to More options: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d 12.4 Data for line chart Format that we have: Day High Temp April 1 60 April 2 43 April 3 43 April 4 56 April 5 45 April 6 62 April 7 49 Format that we need looks something like this: <path class="line" fill="none" d="M0,149.15254237288136L71.42857142857143,264.40677966101697L142.85714285714286,264.40677966101697L214.28571428571428,176.27118644067798L285.7142857142857,250.84745762711864L357.14285714285717,135.59322033898303L428.57142857142856,223.72881355932205"></path> 12.5 Create a line generator Expects data in an array of 2-dimensional arrays, that is, an array of (x,y) pairs: const dataset = [ [0, 60], [1, 43], [2, 43], [3, 56], [4, 45], [5, 62], [6, 49] ]; const mylinegen = d3.line() Test it in the Console: mylinegen(dataset); Add an ordinal scale for x: const xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .range([0, 500]) … and a linear scale for y: const yScale = d3.scaleLinear() .domain([d3.min(dataset, d => d[1]) - 20, d3.max(dataset, d => d[1]) + 20]) .range([400, 0]); *Why d[1] instead of d? (See p. 122) Add accessor functions .x() and .y(): mylinegen .x(d => xScale(d[0])) .y(d => yScale(d[1])); Test again: mylinegen(dataset); Now let’s add a <path> element with that d attribute: (this step is just for learning purposes…) const mypath = mylinegen(dataset); d3.select("svg").append("path").attr("d", mypath) .attr("fill", "none").attr("stroke", "red") .attr("stroke-width", "5"); 12.6 Put the line generator to work Now let’s do it the direct way: bind the datum and calculate the path in one step: d3.select("svg").append("path") .datum(dataset) .attr("d", mylinegen) .attr("fill", "none") .attr("stroke", "teal") .attr("stroke-width", "5"); Finally, we’ll add a class and style definitions: <style> .linestyle { fill: none; stroke: teal; stroke-width: 5px; } </style> The append(\"path\") line becomes: svg.append("path") .datum(dataset) .attr("d", mylinegen) .attr("class", "linestyle"); .linestyle { fill: none; stroke: teal; stroke-width: 5px; } Putting it all together, we have: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Line generator</title> <script src="https://d3js.org/d3.v7.js"></script> <style type ="text/css"> .linestyle { fill: none; stroke: teal; stroke-width: 5px; } </style> </head> <body> <script> const w = 500; const h = 400; const svg = d3.select("svg#noaxes"); const dataset = [ [0, 60], [1, 43], [2, 43], [3, 56], [4, 45], [5, 62], [6, 49] ]; let xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .range([0, w]); let yScale = d3.scaleLinear() .domain([d3.min(dataset, d => d[1]) - 20, d3.max(dataset, d => d[1]) + 20]) .range([h, 0]); const mylinegen = d3.line() .x(d => xScale(d[0])) .y(d => yScale(d[1])); svg.append("path") .datum(dataset) .attr("d", mylinegen) .attr("class", "linestyle"); </script> </body> </html> And another example with axes: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title></title> <script src="https://d3js.org/d3.v7.js"></script> </head> <body> <svg id="withaxes" width="600" height="400"></svg> <script> const svg2 = d3.select("svg#withaxes") const margin = {top: 20, right: 50, bottom: 30, left: 50} const width = +svg2.attr("width") - margin.left - margin.right const height = +svg2.attr("height") - margin.top - margin.bottom const g = svg2.append("g").attr("transform", `translate(${margin.left}, ${margin.top})`); const parseTime = d3.timeParse("%d-%b-%y"); xScale = d3.scaleTime().range([0, width]); yScale = d3.scaleLinear() .domain([20, 80]) .range([height, 0]); const xAxis = d3.axisBottom() .scale(xScale) .tickFormat(d3.timeFormat("%Y-%m-%d")); const line = d3.line() .x(d => xScale(d.date)) .y(d => yScale(d.high)); const data = [{"date":"1-Apr-18","high":60}, {"date":"2-Apr-18","high":43}, {"date":"3-Apr-18","high":43}, {"date":"4-Apr-18","high":56}, {"date":"5-Apr-18","high":45}, {"date":"6-Apr-18","high":62}, {"date":"7-Apr-18","high":49}]; data.forEach(function(d) { d.date = parseTime(d.date); }); xScale .domain(d3.extent(data, d => d.date)); g.append("g") .attr("transform", `translate(0, ${height})`) .call(xAxis); g.append("g") .call(d3.axisLeft(yScale)) g.append("path") .datum(data) .attr("class", "line") .attr("fill", "none") .attr("stroke", "red") .attr("stroke-width", 1.5) .attr("d", line); </script> </body> </html> (Also uses: d3.timeParse() and JavaScript Array.foreach() ) 12.7 Additional Resources Multiple Time Series in D3 by Eric Boxer (EDAV 2018) "],["layouts.html", "13 Layouts 13.1 Lecture slides 13.2 Set up data and stack method 13.3 Set up scales 13.4 Add groups 13.5 Add rectangles 13.6 Get the code", " 13 Layouts IDVW2, Chapter 13 Layouts (d3.stack() only, pp. 264-270) 13.1 Lecture slides layouts.pdf 13.2 Set up data and stack method Open the JavaScript Console // try me in the Console const w = 500; const h = 300; // original data const dataset = [ { apples: 5, oranges: 10, grapes: 22 }, { apples: 4, oranges: 12, grapes: 28 }, { apples: 2, oranges: 19, grapes: 32 }, { apples: 7, oranges: 23, grapes: 35 }, { apples: 23, oranges: 17, grapes: 43 } ]; // set up stack method const stack = d3.stack() .keys([ "apples", "oranges", "grapes" ]) .order(d3.stackOrderDescending); // data, stacked const series = stack(dataset); Try stack(dataset) in the Console. 13.3 Set up scales const xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .range([0, w]) .paddingInner(0.05); const yScale = d3.scaleLinear() .domain([0, d3.max(dataset, d => d.apples + d.oranges + d.grapes)]) .range([h, 0]); const colors = d3.scaleOrdinal(d3.schemeCategory10); Enter d3.schemeCategory10 in the Console. Now try out the colors function. What is the domain? See built-in color options here. Of course you are not limited to these and can use any appropriate color scheme. 13.4 Add groups //Create SVG element const svg = d3.select("#stacked") .append("svg") .attr("width", w) .attr("height", h); // Add a group for each row of data const groups = svg.selectAll("g") .data(series) .enter() .append("g") .style("fill", (d, i) => colors(i)); [There’s a div with id “stacked” here.] Why doesn’t anything show up yet? Right-click and Inspect to find out. 13.5 Add rectangles // Add a rect for each data value const rects = groups.selectAll("rect") .data(d => d) .enter() .append("rect") .attr("x", (d, i) => xScale(i)) .attr("y", d => yScale(d[1])) .attr("height", d => yScale(d[0]) - yScale(d[1])) .attr("width", xScale.bandwidth()); 13.6 Get the code Code for download "],["general-advice.html", "14 General Advice 14.1 Debugging Tips 14.2 Other", " 14 General Advice 14.1 Debugging Tips Make extensive use of Elements to see what’s being added to the DOM. Make extensive use of Console to check the values of variables and/or test code. Pay attention to errors in the Console. Use console.log() esp. in functions Post Minimal Working Examples on Ed Discussion in Canvas. See: “How to create a Minimal, Complete, and Verifiable example” (But don’t worry if it’s not perfect, we’re not going to judge.) Use a text editor that helps you identify unmatched () {} []. Have a tip? Click the button, add the tip, and create a pull request. 14.2 Other Save working versions! Pay attention to the order "],["solutions.html", "15 Solutions ", " 15 Solutions Web tech: shapes Solution Contributed by Tracy Liu D3 in the Console: green circles Select the circle with ID “henry” and make it blue. d3.select("svg") .select("circle#henry") .transition() // optional .duration(1000) // optional .attr("fill","blue"); Select all circles of “apple” class make them red. d3.select("svg") .selectAll("circle.apple") .attr("fill", "red"); Select the first circle and add an orange border (“stroke”), and stroke width (“stroke-width”) of 5. d3.select("svg") .select("circle") .attr("stroke", "orange") .attr("stroke-width", "5"); Select all circles of “apple” class and move them to the middle of the svg. d3.select("svg") .selectAll("circle.apple") .transition() .duration(2000) .attr("cx", d3.select("svg").attr("width") / 2) .attr("cy", d3.select("svg").attr("height") / 2); Contributed by Tracy Liu D3 in the Console: blue circles Move all the circles to the right. const svg = d3.select("svg") svg.selectAll("circle") .transition() .duration(2000) .attr("cx", 450); Move them back to the left and change their color. svg.selectAll("circle") .transition() .duration(2000) .attr("cx", 50) .attr("fill", "red"); In a text editor, add an id to the third circle in six_blue_circles.html, save the file, and then in the Console, move only that circle to the right. svg.select("circle#third") .transition() .duration(2000) .attr("cx", "450"); Move all the circles to the middle of the screen, then move them all to the same location. svg.selectAll("circle") .transition() .duration(2000) .attr("cx", 250) .transition() .duration(2000) .attr("cy", 200); (Extra: return the circles to their starting positions.) const circ = svg.selectAll("circle") .data([100, 150, 200, 250, 300, 350]); circ.transition() .duration(2000) .attr("cx", 50) .attr("cy", d => d) .attr("fill", "blue"); Contributed by Tracy Liu D3 in the Console: data bind const bluedata = [30, 20, 40, 70, 120, 70]; const circ = d3.select("svg") .selectAll("circle") .data(bluedata); circ.transition() .duration(2000) .attr("fill", "pink") .attr("r", d => d / 2) .attr("cx", d => 3 * d); Contributed by Tracy Liu Update, Enter, and Exit: horizontal bar chart For this exercise open up your text editor. We will be operating inside the <script> tags. Our goal is to create a horizontal bar chart. The first step is to create the svg element where our graph will live in. We want to make sure to make it tall and wide enough to hold the data of the given array. We also store our data in an array. const bardata = [300, 100, 150, 225, 75, 275]; const svg = d3.select("body") .append("svg") .attr("width", "700") .attr("height", "400"); Next we will bind the data to the DOM rectangles and store the selection in a variable called bars. Since there are no DOM rectangles (yet), the update and exit selections will be empty. Note that nothing will appear on the screen yet since the enter elements are not combined with DOM elements. const bars = svg.selectAll("rect") .data(bardata); Next step is to create DOM elements from the enter selection and give them the correct attributes to form a horizonal barchart. First we will set x to zero and then in order to set the y distances between the bars we will use each datapoint’s index. The mapping function for the y coordinate is (d, i) => i * 25 + 10 works as follows: When i = 0, y = 10, when i = 1, y = 35, when i = 2, y = 60, etc. Lastly, we want each rectangle’s width to be equal to its data value. bars.enter() .append("rect") .attr("x", 0) .attr("y", (d, i) => i * 25 + 10) .attr("width", d => d) .attr("height", "20") .attr("fill", "pink"); The complete solution is here Contributed by Kassie Papasotiriou Update, Enter, and Exit: merge Change the data to any six other values and update the lengths of the bars. console: const bardata = [130, 210, 90, 300, 200, 50]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(bardata); bars.transition() .duration(2000) .attr("width", d => d); Bind a new dataset, newbardata to the bars, update the bar lengths, and remove any extra bars. const newbardata = [250, 125, 80, 100]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(newbardata); bars.transition() .duration(2000) .attr("width", d => d) bars.exit() .transition() .duration(2000) .attr("width", 0) .remove(); 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. const reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(reallynewbardata); bars.transition() .duration(2000) .attr("width", d => d) bars.enter() .append("rect") .attr("width", 0) .attr("x", 30) .attr("y", (d, i) => 50 * i) .attr("height", 35) .attr("width", d => d) .attr("fill", "lightgreen") .attr("stroke", "pink") .attr("stroke-width", 5); Use .merge() to combine the update and enter selections into one selection and then transition the length of all of the bars to half their current length. const reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275]; const svg = d3.select("svg"); const bars = svg.selectAll("rect") .data(reallynewbardata); bars.enter() .append("rect") .attr("x", 30) .attr("y", (d, i) => 50 * i) .attr("height", 35) .attr("width", d => d) .attr("fill", "lightgreen") .attr("stroke", "pink") .attr("stroke-width", 5) .merge(bars) .transition() .duration(2000) .attr("height", "35") .attr("width", d => d); Add text labels inside the bars at the right end with the length of the bar in pixels. const reallynewbardata = [300, 100, 250, 50, 200, 150, 325, 275]; const svg = d3.select("svg"); const bartext = svg.selectAll("text") .data(reallynewbardata); bartext.enter() .append("text") .attr("x", d => d - 5) .attr("y", (d, i) => 50 * i + 12) .text(d => d); Contributed by Tracy Liu Update, Enter, and Exit: functions Question Answers Since there are no questions we will try out a few things and explain why the bars are behaving that way. Open up the file on Chrome and type the following in you Console: By running the code below we are rebinding the new data to the DOM elements. In this case, the inital data and the new data have the same length so no new elements will be added and none will be removed. We update the data, change the fill and then change the width. update([100, 200, 300, 400, 200, 300]); By running the code below, the two data values are bound to the first two DOM elements. The color and width are changed the extra DOM elements that did not receive data values are removed. update([200, 400]); By running the code below (without refreshing the page from 2.), we bind the data, and two of the values will be in the enter selection. For those two values we create two more DOM elements, fill them with yellow and adjust their width. Next we merge all elements together and to the merge selection we readjust the widths to make sure that all elements have the correct length and we turn them to orange. Note that since in this scenario we had enter elements there will be nothing in the exit selection. update([200, 300, 200, 125]); Update, Enter, and Exit: vertical bar chart Question Answers In order to change a horizontal bar chart to a vertical barchart we need to first flip the x and y coordinates. If we only make this change we will notice that our barchart is not vertical but it is flipped (meaning that all bars seem to be upside-down). This is because the coordinate system in the svg starts from the top left and not the bottom left as we are used to. Therefore in order to bring everything “down”, we need to tweak the y coordinate. In order to do that we can subtract from the height of the svg the data value of each bar. In this way all bars will end at 400 and start d pixels before the end. // Create svg with same data const svg = d3.select("body") .append("svg") .attr("width", "500") .attr("height", "400"); const bardata = [300, 100, 150, 225, 75, 275]; const bars = svg.selectAll("rect") .data(bardata); bars.enter() .append("rect") .attr("x", (d, i) => i * 50 + 50) .attr("y", d => 400 - d) .attr("width", "35") .attr("height", d => d) .attr("fill", "lightgreen"); In addition to that, we need to reflect those changes in the update function and in addition to updating all bar’s heights we need to also update all barsnewy` coordinates. bars.enter() .append("rect") // add new elements .attr("x", (d, i) => i * 50 + 50) .attr("y", d => 400 - d) .attr("width", "35") .attr("height", d => d) .attr("fill", "yellow") .merge(bars) // merge .transition() .duration(2000) .attr("y", d => 400 - d) .attr("height", d => d) .attr("fill", "orange"); The complete solution is here Contributed by Kassie Papasotiriou Transitions: bar chart with transitions code for download rendered version "],["correlation-coefficient.html", "16 Correlation Coefficient", " 16 Correlation Coefficient h2, h3, p, text { font-family: sans-serif; text-anchor: middle; } Correlation Coefficient The correlation coefficient (r) is a measure of the linear relationship between two variables x and y. To get a sense of the connection between the appearance of points – (x,y) pairs – in a scatterplot and the value of r, click anywhere on the graph to add points. To remove points, click the Remove Points button and then mouseover points. The correlation coefficient is shown below. Add points Remove points Click on the chart below to add points. "],["spearman-rank-correlation-coefficient.html", "17 Spearman Rank Correlation Coefficient", " 17 Spearman Rank Correlation Coefficient h2, h3, p, text { font-family: sans-serif; text-anchor: middle; } .rank { fill: white; font-weight: bold; dominant-baseline: central; /* https://stackoverflow.com/questions/12250403/vertical-alignment-of-text-element-in-svg */ } #rho { font-family: serif; font-size: 18pt; } Drag the circles to reorder the rankings in Groups A & B. The correlation coefficient, \\(\\rho\\), is displayed below. \\(\\LARGE \\rho = 1 - \\frac{6 \\Sigma{d_i^2}}{n(n^2 -1)} =\\) \\(d_{i}\\) = difference between the two ranks of each observation \\(n\\) = number of observations "],["population-density.html", "18 Population Density", " 18 Population Density * { font-family: sans-serif; } .source { font-size: 9pt; } New York City Each dot represents a person. Data source: http://www.demographia.com/dm-nyc.htm Standalone version: density.html "],["weather-forecast.html", "19 Weather forecast", " 19 Weather forecast * { font-family: sans-serif; } text { font-size: 12px; } Weather forecast for Columbia University Lat, Lon: 40.807793, -73.962144 (Hover over points for more details.) Fahrenheit Celsius "],["appendix-advanced-css.html", "20 Appendix: advanced CSS 20.1 Buttons", " 20 Appendix: advanced CSS Work-in-progress 20.1 Buttons 20.1.1 .active This is a class not a pseudoclass, indicates which button(s) are pressed. 20.1.2 :active A pseudoclass. Clicking is the main way to trigger an :active state. 20.1.3 :focus A pseudoclass. Mainly used for tabbing. Clicking may focus a button but not always. A box shadow such as box-shadow: 0 0 0 3px lightskyblue; is a good choice 20.1.4 :hover As expected, can have separate hover behavior for .active buttons. 20.1.5 Example See the Pen Button .active vs :active by Joyce Robbins (https://codepen.io/jtr13) on CodePen. "],["404.html", "Page not found", " Page not found The page you requested cannot be found (perhaps it was moved or renamed). You may want to try searching to find the page's new location, or use the table of contents to find the page you are looking for. "]] diff --git a/share-d3-online.html b/share-d3-online.html index 09a50682..4861e0c7 100644 --- a/share-d3-online.html +++ b/share-d3-online.html @@ -23,7 +23,7 @@ - + diff --git a/solutions.html b/solutions.html index 218c8e4a..c36753ba 100644 --- a/solutions.html +++ b/solutions.html @@ -23,7 +23,7 @@ - + diff --git a/spearman-rank-correlation-coefficient.html b/spearman-rank-correlation-coefficient.html index 6888aa8f..e714f3fa 100644 --- a/spearman-rank-correlation-coefficient.html +++ b/spearman-rank-correlation-coefficient.html @@ -23,7 +23,7 @@ - + diff --git a/transitions.html b/transitions.html index b44fbea2..e825681c 100644 --- a/transitions.html +++ b/transitions.html @@ -23,7 +23,7 @@ - + diff --git a/update-enter-and-exit.html b/update-enter-and-exit.html index 52e42786..10ff5d3d 100644 --- a/update-enter-and-exit.html +++ b/update-enter-and-exit.html @@ -23,7 +23,7 @@ - + diff --git a/weather-forecast.html b/weather-forecast.html index f25bb661..bcd6012d 100644 --- a/weather-forecast.html +++ b/weather-forecast.html @@ -23,7 +23,7 @@ - + diff --git a/web.html b/web.html index 305d6e7c..3a27f2d7 100644 --- a/web.html +++ b/web.html @@ -23,7 +23,7 @@ - +