Coding

D3.js – A Practical Introduction

  • 00:00:00 hi in this video we'll have a look at
  • 00:00:02 d3.js I will explain what d3.js is why
  • 00:00:06 it's pretty nice to use it and what we
  • 00:00:08 can do with that now to learn all about
  • 00:00:09 that in this video we're going to build
  • 00:00:11 a very simple first chart with DeFreitas
  • 00:00:14 and we'll get there step by step to
  • 00:00:16 understand what it is how it works and
  • 00:00:18 how you can use it
  • 00:00:25 so let's start with a very important
  • 00:00:28 basic question what exactly is d3.js
  • 00:00:33 d3.js is a library for manipulating
  • 00:00:36 documents based on data this is a nice
  • 00:00:39 sentence you can find in their official
  • 00:00:41 documentation on their official web page
  • 00:00:43 as well what does it mean though well
  • 00:00:46 there are two important parts in this
  • 00:00:48 sentence it's a library for manipulating
  • 00:00:51 documents
  • 00:00:52 so is it like jQuery maybe because
  • 00:00:55 jQuery if you know that it used to be
  • 00:00:58 very popular in the past jQuery also is
  • 00:01:01 a JavaScript library for in the end
  • 00:01:03 manipulating documents so manipulating
  • 00:01:06 the Dom and that is what documents here
  • 00:01:08 means it typically means HTML documents
  • 00:01:11 so is it like jQuery well we have to
  • 00:01:15 consider that second part here based on
  • 00:01:18 data that's the interesting part but
  • 00:01:21 what does this mean well the fridge is
  • 00:01:23 allows you to manipulate documents so it
  • 00:01:26 allows you to manipulate your HTML page
  • 00:01:28 your Dom but it has this strong
  • 00:01:32 connection to data and in the end it
  • 00:01:35 allows you to for example automatically
  • 00:01:38 render or re render HTML and SVG
  • 00:01:42 elements on your page based on data
  • 00:01:45 you make d3.js aware of so you can
  • 00:01:48 basically you could say connect elements
  • 00:01:51 on your page to data and then for
  • 00:01:55 example render multiple divs for
  • 00:01:57 multiple data points in your data or
  • 00:01:59 update the Dom when your data changes
  • 00:02:02 now that might still be relatively
  • 00:02:05 abstract will therefore of course have a
  • 00:02:07 more detailed look at this and see
  • 00:02:08 concrete examples but in a nutshell this
  • 00:02:11 is what d3.js is all about and this is
  • 00:02:14 how the free J's code looks like you can
  • 00:02:17 for example reach out to a div on your
  • 00:02:19 page select it maybe select all
  • 00:02:22 paragraphs in there for the moment you
  • 00:02:25 see there are no paragraphs in there but
  • 00:02:27 you'll see how this code works
  • 00:02:28 throughout this video then connect some
  • 00:02:31 data and that is a key part connecting
  • 00:02:34 data and then define what should happen
  • 00:02:37 if that data is can
  • 00:02:38 but for the first time or if new data
  • 00:02:41 was added and for example a render extra
  • 00:02:44 paragraph elements with some text inside
  • 00:02:47 of them for death data now that might
  • 00:02:50 still be very abstract so let's maybe
  • 00:02:52 just dive right in and write some code
  • 00:02:54 now for that we first of all need to add
  • 00:02:57 d3.js to our project and for that we can
  • 00:03:00 simply grab that link we find on the
  • 00:03:02 official page d3.js org and then simply
  • 00:03:05 dive into a HTML document which you have
  • 00:03:08 here I created a brand new one a pretty
  • 00:03:10 empty one just with a base skeleton and
  • 00:03:13 add this import before you have your
  • 00:03:16 script code so here I have to defer ejs
  • 00:03:19 import and here i have an import to my
  • 00:03:22 own app.js file where I'm going to write
  • 00:03:24 my own code here so now with that d3.js
  • 00:03:28 is added now we can write D free J's
  • 00:03:31 code or we can work with it and why
  • 00:03:33 don't we get started with this example
  • 00:03:35 here so that we can understand what
  • 00:03:37 happens here for that well first of all
  • 00:03:41 add a div here on this HTML page so
  • 00:03:45 instead of the body an empty div just
  • 00:03:47 like this and now an apt Reyes we can
  • 00:03:50 use d3 this is available because of our
  • 00:03:53 import here that unlocks a global d3
  • 00:03:57 object which is now available and you
  • 00:04:00 can console.log do you free if you're
  • 00:04:02 not sure or if you want to see what's
  • 00:04:04 inside of that here if I open my console
  • 00:04:07 this is what it prints so this is this
  • 00:04:09 d3.js object full of helper methods and
  • 00:04:13 useful functionalities and one key thing
  • 00:04:15 we can do with d3 here is we can call
  • 00:04:19 the Select method on it
  • 00:04:22 now select does what the name implies it
  • 00:04:24 allows you to select an element in your
  • 00:04:27 Dom you have select to select a single
  • 00:04:29 element and select all to select
  • 00:04:31 multiple elements because with the free
  • 00:04:33 Jas and that's one of its key features
  • 00:04:35 and strong powers you can actually
  • 00:04:38 select multiple elements at the same
  • 00:04:40 time and manipulate them all at the same
  • 00:04:42 time and that is also another difference
  • 00:04:44 to jquery where something like this is
  • 00:04:47 not the main focus at least with the
  • 00:04:49 free j/s it is a core focus and it is
  • 00:04:51 very easy
  • 00:04:52 nonetheless here I just want to select a
  • 00:04:54 div and for that we can pass in a string
  • 00:04:56 with div inside of it and what you have
  • 00:04:59 here in the end doesn't have to be a
  • 00:05:01 attack you can have any valid CSS
  • 00:05:03 selector in here so CSS class name would
  • 00:05:08 also be possible if you add a dot at the
  • 00:05:10 beginning or by ID with the hash symbol
  • 00:05:12 but I want to select by a tag and
  • 00:05:16 therefore div selects the first div
  • 00:05:18 element which it finds on the page so
  • 00:05:21 now we get hold of that now we can do
  • 00:05:24 something which might look strange at
  • 00:05:25 first I call select all on this and by
  • 00:05:29 calling it on the selected div I
  • 00:05:31 effectively would now want to select
  • 00:05:33 elements inside of the div the
  • 00:05:35 interesting thing of course is that this
  • 00:05:37 div is empty so there is nothing to
  • 00:05:38 select inside of it well stick with me
  • 00:05:41 for now it will make more sense in a
  • 00:05:43 second let's select let's say all
  • 00:05:46 paragraph elements in there and as I
  • 00:05:49 said I'm fully aware that at the moment
  • 00:05:50 there are no paragraph elements but
  • 00:05:53 let's nonetheless select all elements in
  • 00:05:55 there and what this gives us is again a
  • 00:05:58 selection so select just like select all
  • 00:06:00 gives you a selection and all selections
  • 00:06:03 you can always call the same methods for
  • 00:06:05 example here we could again call select
  • 00:06:07 all to select all elements in all those
  • 00:06:10 paragraphs which we selected now since
  • 00:06:12 we don't even have paragraphs here at
  • 00:06:14 the moment I don't want us like anything
  • 00:06:16 else instead now comes something
  • 00:06:18 important on a selection we can call
  • 00:06:21 data in the end to bind this selection
  • 00:06:24 to that data and data here typically is
  • 00:06:28 an array for example here 1 2 3 but it
  • 00:06:33 could also be an array full of
  • 00:06:34 JavaScript objects or full of strings so
  • 00:06:38 now all paragraphs inside of the div are
  • 00:06:41 bound to this data to this array now of
  • 00:06:44 course there are no paragraphs but now
  • 00:06:47 come something interesting we can also
  • 00:06:49 bind elements which don't exist yet to
  • 00:06:52 data so that we automatically generate
  • 00:06:55 them when that data is there so once we
  • 00:06:58 set up this binding and we do that by
  • 00:07:01 now calling enter on our data which in
  • 00:07:05 the end creates an
  • 00:07:06 new selection which is basically a
  • 00:07:08 difference between the paragraphs with
  • 00:07:12 data that were rendered before and that
  • 00:07:16 should now be rendered because of this
  • 00:07:18 data binding so you can basically read
  • 00:07:20 this as select the div select all
  • 00:07:23 paragraphs in there then bind data to
  • 00:07:26 that paragraph and then tell me which
  • 00:07:29 paragraphs are missing and of course at
  • 00:07:32 the beginning since we have no
  • 00:07:33 paragraphs in there we get free missing
  • 00:07:36 paragraphs because we got free data
  • 00:07:38 points here free elements in that array
  • 00:07:40 and we're saying please give me all the
  • 00:07:42 missing elements all the missing
  • 00:07:44 paragraphs to which this data is found
  • 00:07:46 so enter now Andy and holds information
  • 00:07:49 about these free missing elements these
  • 00:07:52 free missing data points and on this
  • 00:07:54 selection we can now call append to
  • 00:07:57 append a new paragraph for every missing
  • 00:08:00 paragraph so this will now in the end
  • 00:08:02 add the missing paragraphs to this div
  • 00:08:05 this is very strange when you read it
  • 00:08:08 for the first time and when you hear it
  • 00:08:10 for the first time but this is something
  • 00:08:12 you just have to get used to and then it
  • 00:08:13 makes a lot of sense once you always
  • 00:08:16 keep in mind that the free jeaious is
  • 00:08:18 all about binding data to elements and
  • 00:08:20 then rendering these elements as they
  • 00:08:23 are required so now we're saying give me
  • 00:08:25 all the missing elements and for every
  • 00:08:27 missing element you render do add such a
  • 00:08:30 paragraph and that's by the way
  • 00:08:32 important just to select elements and
  • 00:08:35 add new Dom nodes just for that we
  • 00:08:38 wouldn't need d3.js we could use jQuery
  • 00:08:41 or just the native Dom api's which are
  • 00:08:43 pretty good at this right now
  • 00:08:44 but to have this data binding and make
  • 00:08:48 sure that we react to changes in data
  • 00:08:50 and so on for this we need C free J's
  • 00:08:53 because now this simple code snippet
  • 00:08:55 will render three new paragraphs in that
  • 00:08:58 div one for every data point here just
  • 00:09:02 with this code and if we would want to
  • 00:09:04 do something like this with native Dom
  • 00:09:06 code and so on this would take a bit
  • 00:09:08 more code especially when we then later
  • 00:09:11 also see how we can change that data and
  • 00:09:13 automatically update what's in the DOM
  • 00:09:17 so now I'm not done though I want to set
  • 00:09:20 some text in all those paragraphs and we
  • 00:09:22 don't do this with a pend but instead
  • 00:09:24 now with a text method which basically
  • 00:09:26 takes this selection so this paragraph
  • 00:09:30 which is created multiple times and for
  • 00:09:32 every created paragraph it will now set
  • 00:09:34 the text inside of that so it will add a
  • 00:09:36 text note inside of the paragraph
  • 00:09:38 element and text ever takes some static
  • 00:09:41 text like hello or if you want also a
  • 00:09:45 function where you get access to the
  • 00:09:48 data for this specific paragraph element
  • 00:09:51 that was rendered three elements are
  • 00:09:53 rendered one for each data point so here
  • 00:09:56 data gives you access to each data point
  • 00:09:59 for each paragraph and then for example
  • 00:10:01 here I can just return data in this
  • 00:10:03 function to basically say the paragraph
  • 00:10:06 which is rendered for the first data
  • 00:10:08 point should output one as text the
  • 00:10:12 second paragraph because the data point
  • 00:10:14 value is two should output to the third
  • 00:10:17 one because it's data point value is
  • 00:10:19 free should output free with all of that
  • 00:10:22 if we save that and we reload here we
  • 00:10:26 see one Q free being rendered here now
  • 00:10:29 this might not be the most exciting web
  • 00:10:31 app you've ever seen but this hopefully
  • 00:10:33 gives you a first idea of how D free
  • 00:10:36 jeaious works now typically though you
  • 00:10:39 don't necessarily use d3.js to just
  • 00:10:41 render some text but you can use it for
  • 00:10:44 that and this is really important to me
  • 00:10:45 because often when people hear d3.js
  • 00:10:49 they think of it as a charting library
  • 00:10:52 as a library that makes it easy to
  • 00:10:54 render charts now the thing is indeed
  • 00:10:57 you can use the free J's to render
  • 00:11:00 charts and as you can see by these
  • 00:11:02 examples here it's a pretty common use
  • 00:11:05 case but d3.js is not limited to that
  • 00:11:08 it's a general library for manipulating
  • 00:11:11 documents you can render anything with
  • 00:11:13 it text numbers charts shapes whatever
  • 00:11:17 you want it's not limited to charts if
  • 00:11:20 you just need charts our libraries like
  • 00:11:23 chart J s might be the better choice
  • 00:11:25 because those are heavily focused on
  • 00:11:28 charts and probably make that easy
  • 00:11:31 then the free j/s with the free jsut got
  • 00:11:34 more power you can build up a chart from
  • 00:11:36 scratch you can find unit to your
  • 00:11:38 requirements and you can do more than
  • 00:11:40 that but of course that also means that
  • 00:11:41 you need to do more work now with that
  • 00:11:44 said however let's see how we can render
  • 00:11:46 a basic chart if we want you to do that
  • 00:11:50 let's start with some dummy data now
  • 00:11:53 this would be data which you in reality
  • 00:11:54 might be fetching from some server or
  • 00:11:57 from a file but here it's just some
  • 00:12:00 hard-coded data so that we have some
  • 00:12:02 data to output let's say every data node
  • 00:12:04 has an ID has a value and let's say
  • 00:12:08 we're working with some sales data here
  • 00:12:11 so maybe we have a region but this is
  • 00:12:14 totally up to you I'm just coming up
  • 00:12:15 with some fictional data here so there
  • 00:12:17 we might have us a and then we got our
  • 00:12:21 other three data points and you could
  • 00:12:24 add more data points of course and let's
  • 00:12:26 say here we have India we got China and
  • 00:12:32 because I'm from Germany we also got
  • 00:12:34 Germany here but you can add more data
  • 00:12:37 if you want to now this is the data
  • 00:12:39 which we let's say wanna output in a bar
  • 00:12:41 chart so a simple bar chart is what you
  • 00:12:44 want to render therefore of course we're
  • 00:12:47 not going to render a bunch of
  • 00:12:48 paragraphs here but some other data
  • 00:12:50 nonetheless before we completely remove
  • 00:12:52 that if we just swap the dummy data down
  • 00:12:55 here for the dummy data constant I
  • 00:12:57 defined up here you will see that here
  • 00:13:01 in this function we can now access for
  • 00:13:03 example data reaching and if we save
  • 00:13:06 this and I reload here you see the
  • 00:13:08 regions being output here so that's just
  • 00:13:10 to show you how easy it is to render
  • 00:13:13 notes element Dom no it's based on data
  • 00:13:16 still that's not the main thing we want
  • 00:13:19 to do here instead inside of that div
  • 00:13:21 let's say we want to render this bar
  • 00:13:23 chart for this first of all I'll select
  • 00:13:26 the div and I actually want to change
  • 00:13:28 its style and that is also something you
  • 00:13:30 can do with d3.js you can set the
  • 00:13:32 attributes and specifically also the CSS
  • 00:13:35 classes or the inline styles of Dom
  • 00:13:37 elements for example the inline Styles
  • 00:13:40 can be set with the style method the
  • 00:13:43 CSS classes could be attached with the
  • 00:13:46 clast method but I'll go for the style
  • 00:13:49 method and on that div let's say I want
  • 00:13:52 to set a border to one pixel solid and
  • 00:13:54 red and if I do that we see nothing or
  • 00:13:58 we see this year but we don't see a real
  • 00:14:00 box or anything like that because this
  • 00:14:03 div is missing things like a width and a
  • 00:14:05 height now you can set everything with
  • 00:14:08 CSS as you're used to I'm just using
  • 00:14:10 d3.js here to show you how it works but
  • 00:14:14 let me also show you how we could add a
  • 00:14:15 class here with the class method I could
  • 00:14:18 add my container CSS class and now if I
  • 00:14:23 add a basic inline style here let's say
  • 00:14:27 just like that and of course you could
  • 00:14:29 always use a CSS file but if I use that
  • 00:14:31 here and I didn't have in my container
  • 00:14:33 selector and I give this a width of
  • 00:14:35 let's say 250 pixels and a height of 200
  • 00:14:40 pixels you will see that now I get an
  • 00:14:45 error simply because clost actually
  • 00:14:48 takes the second argument which defines
  • 00:14:50 whether that class should be added or
  • 00:14:51 not and here I want to add it so I set
  • 00:14:54 this to true you have this two arguments
  • 00:14:56 set up so that you could change this
  • 00:14:58 dynamically and toggle a class for
  • 00:15:00 example but with true this works and now
  • 00:15:03 we have this nice container now in there
  • 00:15:05 I wanna render my bar chart that's the
  • 00:15:07 idea so to do that to render the bar
  • 00:15:10 chart here we need to again select the
  • 00:15:13 div and work with it we need to render
  • 00:15:17 elements inside of the div so first of
  • 00:15:20 all I'll store that selection here in a
  • 00:15:22 container constant so that we can always
  • 00:15:24 just refer to container and work with
  • 00:15:27 that style Dave here now to add some
  • 00:15:30 elements here we want to select all the
  • 00:15:34 nodes which we eventually want to add
  • 00:15:36 and that could be for example more divs
  • 00:15:41 and then bind some data to that now one
  • 00:15:44 important note though if you select all
  • 00:15:47 divs here in the container by default
  • 00:15:50 this would select the container as well
  • 00:15:52 because that awls is a div and it will
  • 00:15:54 include that selection on which you call
  • 00:15:57 all now to rule that out we could select
  • 00:16:00 for example by a CSS class like bar and
  • 00:16:03 make sure that the elements we are about
  • 00:16:06 to render half that CSS class later now
  • 00:16:10 we can find our dummy data here with the
  • 00:16:14 data method and now again call enter to
  • 00:16:18 find out which data wasn't rendered yet
  • 00:16:20 and when this app first loads of course
  • 00:16:22 nothing was rendered so this will be a
  • 00:16:25 full selection full of four data points
  • 00:16:28 which should be rendered so then we can
  • 00:16:30 append a new div here for every missing
  • 00:16:34 element and on every div I want to add
  • 00:16:37 the bar class here so that later we can
  • 00:16:41 select Vitus so this will now give me
  • 00:16:44 access to all my bars so all the bars in
  • 00:16:47 the bar chart at the moment of course
  • 00:16:49 not much is happening but we are
  • 00:16:51 rendering a bunch of divs if I reload we
  • 00:16:54 don't see anything but if we inspect
  • 00:16:56 this here you'll see instead of the diff
  • 00:16:58 there are four bar deaths being rendered
  • 00:17:01 now in order to make sure that we do is
  • 00:17:04 see them I will add a nice styling here
  • 00:17:07 since they have the bar class we can
  • 00:17:09 target this alternatively we could of
  • 00:17:12 course also set Styles here with the
  • 00:17:14 style method but all you CSS styles and
  • 00:17:17 give every bar let's say a background
  • 00:17:20 color of 5 – 1 7 5 1 or actually maybe a
  • 00:17:26 little more in this area so it's a nice
  • 00:17:27 purple color so 7 – 0 5 7 0 is the color
  • 00:17:32 I'm using here now I'll not set the
  • 00:17:34 width and the height here though instead
  • 00:17:37 I'll do this here in app jeaious with
  • 00:17:39 JavaScript for this we can use the actor
  • 00:17:43 method or also the style method actor
  • 00:17:47 would allow us to set the width
  • 00:17:49 attribute directly on the element style
  • 00:17:51 allows us to set the width style which
  • 00:17:53 all the works and I want to set the
  • 00:17:55 width style
  • 00:17:56 and later we want to dynamically adjust
  • 00:17:58 the width based on the value so that the
  • 00:18:01 bars are not equally sized but respect
  • 00:18:04 the different values but for the moment
  • 00:18:06 I'll just set the width to let's say
  • 00:18:07 armed 100
  • 00:18:11 and fifty pixels and not the wif sorry
  • 00:18:15 the wif should be let's say we have a
  • 00:18:17 total container with of 250 since we
  • 00:18:20 have four data points let's maybe go
  • 00:18:22 with fifty pixels and the height should
  • 00:18:26 now be let's say 150 pixels and with
  • 00:18:29 that if I reload you see this bar here
  • 00:18:33 pretty large but the reason for that is
  • 00:18:37 that these are all the different divs
  • 00:18:39 just below each other they're not
  • 00:18:42 rendered side-by-side they're rendered
  • 00:18:43 below each other now of course I want to
  • 00:18:47 have them next to each other
  • 00:18:48 horizontally and to achieve this of
  • 00:18:52 course here in the container we could
  • 00:18:54 set display to flex and justify content
  • 00:18:57 space around and if I now reload all
  • 00:19:00 these bars are sitting next to each
  • 00:19:03 other just because of the diferencia saz
  • 00:19:06 styling now of course this is not a
  • 00:19:09 realistic bar chart though because all
  • 00:19:11 the bars have the same height and we
  • 00:19:14 typically might want to adjust this
  • 00:19:16 based on the actual data point for
  • 00:19:18 example China should have the the
  • 00:19:21 tallest bar Germany should have the
  • 00:19:22 smallest so to achieve this we need to
  • 00:19:26 set the height here dynamically and not
  • 00:19:28 hard-coded that the cool thing is just
  • 00:19:31 as with the text earlier where you could
  • 00:19:33 pass in a hard-coded value or a function
  • 00:19:36 to get access to the data this Dom node
  • 00:19:39 is bound to you can do the same for
  • 00:19:41 basically all other methods you have
  • 00:19:43 here including the style method the
  • 00:19:45 value which is wanted here can be a
  • 00:19:47 hard-coded one or you pass in a function
  • 00:19:50 that gets access to the data point that
  • 00:19:53 is responsible for rendering this
  • 00:19:55 concrete div so therefore this function
  • 00:19:57 will be called once for each stiff and
  • 00:19:59 therefore in total four times once for
  • 00:20:01 every data point so this is the value
  • 00:20:03 for the data point for which a new div
  • 00:20:06 is being rendered and we get access to
  • 00:20:08 that data and now we could simply take
  • 00:20:10 that value let's say times 15
  • 00:20:15 something like this and use this as a
  • 00:20:17 width so that we use data dot value data
  • 00:20:20 is the entire object and we have a value
  • 00:20:23 here that's why we use data dot value
  • 00:20:26 times free at times 15 sorry
  • 00:20:33 like this plus pixels so Plus this to
  • 00:20:38 convert it to a string and add pixel
  • 00:20:40 because we still need a string here as a
  • 00:20:42 value and that string should contain a
  • 00:20:44 valid CSS value with that if we now save
  • 00:20:47 this you see bars of different height
  • 00:20:49 now that's where we can make the next
  • 00:20:52 step
  • 00:20:53 d3.js is great for document
  • 00:20:55 manipulations and something like this is
  • 00:20:57 fairly easy to achieve as you can tell
  • 00:20:59 that's not a lot of code these are just
  • 00:21:01 19 lines and six lines of that are just
  • 00:21:04 our dummy data but d3.js is not limited
  • 00:21:08 to HTML and if we switch to SVG we are
  • 00:21:12 way more flexible when it comes to
  • 00:21:14 rendering content and to laying it out
  • 00:21:16 correctly and why are we more flexible
  • 00:21:19 with SVG because with SVG if we're
  • 00:21:22 rendering a SVG element and then content
  • 00:21:25 in that element we actually can work in
  • 00:21:28 a coordinate system which gives us a
  • 00:21:30 more fine-grained control over where in
  • 00:21:32 the coordinate system which elements
  • 00:21:35 should be positioned and we don't have
  • 00:21:36 to use CSS layout concepts like flexbox
  • 00:21:40 to position elements instead we can use
  • 00:21:42 data to position elements in that
  • 00:21:44 coordinate system and that's closer to
  • 00:21:47 what we do in charts anyways they use
  • 00:21:49 coordinate systems they use x and y axis
  • 00:21:53 so that's why you typically use SVG when
  • 00:21:56 you want a render charts or charts data
  • 00:21:58 so for dad and index.html I will switch
  • 00:22:02 from div to SVG here so that we have an
  • 00:22:05 SVG element here which is still a
  • 00:22:08 regular HTML element but well we use SVG
  • 00:22:11 under the hood then and here therefore
  • 00:22:14 we select SVG and here we don't render a
  • 00:22:17 div but a rect let's say a rectangle
  • 00:22:20 this is also a valid SVG element which
  • 00:22:22 we can use inside of a SVG node we can
  • 00:22:25 still give this a CSS class this doesn't
  • 00:22:28 change and we can still set the width
  • 00:22:30 and the height however we shouldn't do
  • 00:22:32 this with style instead with a true and
  • 00:22:36 then you all don't need to provide a
  • 00:22:38 string here with pixel instead you can
  • 00:22:41 just insert a number and it will
  • 00:22:42 automatically be treated as pixels
  • 00:22:45 you
  • 00:22:47 if we do that we get a slightly
  • 00:22:51 different result than before we do see a
  • 00:22:54 bar but it seems like all bars are are
  • 00:22:56 on top of each other and they're not
  • 00:22:58 laid out horizontally and they also lost
  • 00:23:00 the color we do see the different
  • 00:23:03 rectangles being rendered though and
  • 00:23:04 they have the right class well the color
  • 00:23:08 is missing because SVG elements
  • 00:23:12 rectangles and so on are not styled with
  • 00:23:14 background color but with fill fill is
  • 00:23:17 simply how you set the background color
  • 00:23:19 the fill color of SVG elements we also
  • 00:23:23 see that flexbox has no effect here and
  • 00:23:26 therefore we can remove it there is a
  • 00:23:27 more elegant way of laying things out
  • 00:23:29 with d3.js anyways and whilst I'm here
  • 00:23:32 already I'll actually set up order of
  • 00:23:35 one pixel solid and that same purple I
  • 00:23:38 have down there on the container like
  • 00:23:40 this and that of course means that in
  • 00:23:42 app tray as we can't get rid of this
  • 00:23:43 style assignment which was just there
  • 00:23:46 for demo purposes anyways so if that
  • 00:23:49 they have the right color but they're
  • 00:23:51 still not laid out correctly and that's
  • 00:23:53 happening because of this coordinate
  • 00:23:55 system now unlike with regular HTML
  • 00:23:58 elements and CSS which we then use to
  • 00:24:01 lay elements out in SVG we use that
  • 00:24:03 internal coordinate system which exists
  • 00:24:06 in that SVG container here and currently
  • 00:24:09 we're not assigning any positions to any
  • 00:24:11 of the rectangles in there therefore
  • 00:24:13 they all have the same position and that
  • 00:24:16 by default is the top-left corner that's
  • 00:24:19 by the way important the coordinate
  • 00:24:21 system in the SVG element starts in the
  • 00:24:24 top-left corner not at the bottom left
  • 00:24:26 what we're typically used to from charts
  • 00:24:28 but in the top left that's why here
  • 00:24:31 these rectangles sit all in the top left
  • 00:24:34 border and actually sit on top of each
  • 00:24:36 other because they all have that point
  • 00:24:38 top left corner on top of each other
  • 00:24:40 therefore and that's what I said
  • 00:24:42 d3.js gives us a nicer way of laying
  • 00:24:45 things out because instead of styling
  • 00:24:47 this with CSS which means that we have
  • 00:24:49 to control margin and spacing and
  • 00:24:52 positions in CSS it would be nicer if we
  • 00:24:55 could lay everything out here and we
  • 00:24:58 don't have to do this with CSS
  • 00:25:00 fools where we manually have to
  • 00:25:02 calculate things like to hide and width
  • 00:25:05 and maybe the positioning but instead if
  • 00:25:07 we could let the free j/s calculate this
  • 00:25:10 for us because after all that is one of
  • 00:25:12 the reasons why we use d free J s it's
  • 00:25:14 great for working with data and for
  • 00:25:17 helping us bring that data to the screen
  • 00:25:19 and indeed it also helps us with
  • 00:25:21 calculating positions of elements and so
  • 00:25:23 on so that for example if we have four
  • 00:25:26 data points and we want to render four
  • 00:25:29 bars next to each other the free J's
  • 00:25:31 helps us render things nicely positioned
  • 00:25:34 next to each other now for that we need
  • 00:25:36 to bring in an extra package though you
  • 00:25:39 can search for d3.js scale because d3.js
  • 00:25:43 is a modular library d3.js itself which
  • 00:25:47 we already imported just has all the
  • 00:25:50 core functionalities so this package
  • 00:25:52 here then if you need functionalities
  • 00:25:55 that for example help you with scaling
  • 00:25:57 and with deriving positions of elements
  • 00:26:01 you need to bring in the additional d3
  • 00:26:03 scale package which depends on the free
  • 00:26:06 J's but adds extra functionalities to
  • 00:26:09 add it you can simply grab such a link
  • 00:26:11 here D free scale V freemen in my case
  • 00:26:17 and add this in your index.html file
  • 00:26:21 after the D free J's import before your
  • 00:26:26 apt is import and we can also add the
  • 00:26:29 Fourier to make sure that this is not
  • 00:26:31 getting executed too early and that this
  • 00:26:33 all executes in order here so back to
  • 00:26:37 App jeaious
  • 00:26:38 now here we should be able to set up a
  • 00:26:41 scaling function which essentially is a
  • 00:26:44 function that helps us calculate
  • 00:26:45 positions of different data points that
  • 00:26:48 are related to each other for that we
  • 00:26:51 add a new constant and we can name it x
  • 00:26:54 scale and that should give us a function
  • 00:26:56 that allows us to calculate the position
  • 00:26:59 on the x-axis and we call d3 scale band
  • 00:27:05 to basically give us an ordinal scale so
  • 00:27:10 basically a scale where every item
  • 00:27:12 should have the same width there also
  • 00:27:15 are other scales and we will need
  • 00:27:17 another scale for the height for example
  • 00:27:19 but when it comes to the width all bars
  • 00:27:22 should have the same width and scale
  • 00:27:24 band basically gives us a uniform
  • 00:27:26 distribution where all items have the
  • 00:27:28 same width now in order to let d3
  • 00:27:31 calculate the width of every item we
  • 00:27:33 need to let d3 know how much space is
  • 00:27:35 available we did it by chaining a method
  • 00:27:38 here on the result of scale band and
  • 00:27:40 that's the range round method this
  • 00:27:42 basically tells the free J's which space
  • 00:27:44 is available and it wants an array which
  • 00:27:47 has a from Q value so from 0 Q the
  • 00:27:51 entire width you have available for
  • 00:27:52 example now we're working with a
  • 00:27:55 container here for our chart and that
  • 00:27:57 container has a width of 250 pixels so
  • 00:28:01 here we have 250 as an upper bound and
  • 00:28:04 this in the end let's do free J's figure
  • 00:28:06 out how much space every item should
  • 00:28:08 have now we also call another method on
  • 00:28:12 the result of this and that is padding
  • 00:28:15 which allows us to define a percentage
  • 00:28:18 padding between the items and I'll set
  • 00:28:20 this to 0.1 for essentially just a tiny
  • 00:28:23 bit of padding between the different
  • 00:28:26 bars
  • 00:28:28 with that we have the X scale now we
  • 00:28:31 also want a Y scale which allows us to
  • 00:28:34 calculate the height of the data points
  • 00:28:36 dynamically for that we call the freeze
  • 00:28:38 scale linear and by the way scale band
  • 00:28:41 and scale linear are methods which are
  • 00:28:44 only available because of this D free
  • 00:28:46 scale import so scale linear allows us
  • 00:28:51 to now calculate the right value the
  • 00:28:54 right height for example for the
  • 00:28:56 different data points taking into
  • 00:28:58 account different values for the value
  • 00:29:00 property so now unlike scale band this
  • 00:29:03 will not give us the same width for
  • 00:29:05 every data point or the same height
  • 00:29:06 instead it will give us different values
  • 00:29:09 now actually to be entirely correct both
  • 00:29:12 scale band and scale linear will not
  • 00:29:16 give us a width and a height but instead
  • 00:29:18 they give us functions that allow us to
  • 00:29:21 translate a value cue another number to
  • 00:29:26 be precise they will give us information
  • 00:29:28 about the X and the y-axis of where
  • 00:29:32 elements should be positioned and for
  • 00:29:34 that it is important to understand that
  • 00:29:36 with the D free scale package we
  • 00:29:40 basically give the free information
  • 00:29:42 about these two axes so x and y and D
  • 00:29:47 free will then be able to position
  • 00:29:49 elements along those axes and with scale
  • 00:29:52 band and scale linear we create
  • 00:29:55 functions that will allow us to generate
  • 00:29:58 positions and sizes within that
  • 00:30:01 coordinate system D free will be aware
  • 00:30:04 of sounds very abstract we'll see it in
  • 00:30:07 action but that is what the scale
  • 00:30:09 methods here in the end will do and what
  • 00:30:12 the idea behind them is and now here on
  • 00:30:15 scale linear we want to call domain and
  • 00:30:18 what domain does is it basically allows
  • 00:30:21 us to specify which min and Max value we
  • 00:30:25 want to be able to map into our chart in
  • 00:30:29 this case so we enter an array here and
  • 00:30:31 now we're going to render this value and
  • 00:30:33 the smallest possible value we
  • 00:30:36 theoretically could have is 0 so
  • 00:30:39 basically the x act
  • 00:30:41 should cross the y-axis at zero this is
  • 00:30:44 the smallest value we want to have on
  • 00:30:46 the y-axis so to say and the biggest
  • 00:30:48 value let's say is 15 so that we have
  • 00:30:50 some empty space above China in this
  • 00:30:53 case we could go for 12
  • 00:30:54 but then the bar of China would go all
  • 00:30:56 the top to our chart so to have a little
  • 00:30:59 bit of empty space at the top let's use
  • 00:31:01 15-year so in the end domain is our way
  • 00:31:06 of letting d3 know about the min and Max
  • 00:31:09 values it has to deal with so we let it
  • 00:31:12 know about the range of values it should
  • 00:31:14 be able to map into its internal
  • 00:31:16 coordinate system which later is
  • 00:31:18 rendered to the screen and here I'm
  • 00:31:21 saying my values are between 0 and 15
  • 00:31:24 please position my values which in
  • 00:31:27 reality are between 6 and 12 inside of a
  • 00:31:30 system that has room for values down to
  • 00:31:33 0 and up to 15 because if you look at a
  • 00:31:37 chart anywhere doesn't matter which kind
  • 00:31:39 of chart typically of course the
  • 00:31:42 smallest value on the y axis is not the
  • 00:31:45 smallest value rendered in a chart but
  • 00:31:47 it typically is 0 and the biggest value
  • 00:31:49 on the y axis typically is not the
  • 00:31:51 biggest value in the chart but instead a
  • 00:31:53 value above that biggest value so that
  • 00:31:56 there is a little bit of extra free
  • 00:31:57 space at the top but that's in the end
  • 00:31:59 what we're setting up here and then on
  • 00:32:02 that we can call their range method so
  • 00:32:05 not range frown but just range and here
  • 00:32:09 feed in the actual available space in
  • 00:32:12 pixels and there we of course have a
  • 00:32:15 height of 200 pixels and the important
  • 00:32:18 thing is that you start with the max
  • 00:32:21 value so with 200 and go all the way to
  • 00:32:24 zeros to the bottom now we have to start
  • 00:32:27 with the bigger value here 200 as a
  • 00:32:30 first value because the coordinate
  • 00:32:33 system d3.js has in mind so which it
  • 00:32:37 kind of uses behind the scenes to then
  • 00:32:39 later generate our positions and sizes
  • 00:32:41 that coordinate system starts in the top
  • 00:32:45 left corner so the position x0 y0 is in
  • 00:32:50 the top left not in the bottom left as
  • 00:32:53 it typically is in our course
  • 00:32:54 systems so because of that for the
  • 00:32:57 x-axis it is left right there we use a
  • 00:33:01 range where we start at zero and go up
  • 00:33:03 to our biggest value but for the y-axis
  • 00:33:05 since we start at the top and go to the
  • 00:33:08 bottom and not the other way around as
  • 00:33:10 we are used to we have to switch those
  • 00:33:13 two values and the biggest value comes
  • 00:33:15 first and then we go to the smallest
  • 00:33:17 value so if that we set up X scale and Y
  • 00:33:21 scale and both are now simply objects
  • 00:33:26 and all the functions which we can use
  • 00:33:28 to calculate concrete values for a width
  • 00:33:30 and height based on the data point that
  • 00:33:33 is being rendered we can use it down
  • 00:33:36 there when we render our bars on every
  • 00:33:39 bar instead of having a hard-coded with
  • 00:33:41 we can call X scale dot bandwidth as a
  • 00:33:45 function like this all lowercase since
  • 00:33:48 every bar has the same width we don't
  • 00:33:50 need to pass in any data specific value
  • 00:33:52 instead this will just give us well an
  • 00:33:54 equal value for every bar and in the end
  • 00:33:57 it does that by taking the available
  • 00:34:00 width and dividing it by the number of
  • 00:34:03 data points we have taking into account
  • 00:34:05 some extra padding now for the height
  • 00:34:09 it's a bit different there we want to
  • 00:34:11 keep that anonymous function but we're
  • 00:34:13 going to use something from the data now
  • 00:34:15 to translate it into actual height and
  • 00:34:18 pixels that takes into account the
  • 00:34:21 available range but also our theoretical
  • 00:34:23 min and Max values here and to do that
  • 00:34:27 we just call Y scale here as a function
  • 00:34:31 and we pass in data dot value as a well
  • 00:34:37 value and this will translate it into an
  • 00:34:40 actual value that's being rendered if we
  • 00:34:44 now reload we see something but it looks
  • 00:34:49 like all the bars are now simply stacked
  • 00:34:51 on top of each other and there's a good
  • 00:34:54 reason for that currently they all have
  • 00:34:55 the same width and they shouldn't have
  • 00:34:58 that of course because of my scaling
  • 00:35:00 here and certainly they shouldn't all
  • 00:35:04 take the total amount of with the total
  • 00:35:07 available width well that they all take
  • 00:35:09 the total amount of width is my error we
  • 00:35:13 also have to specify a domain here for X
  • 00:35:16 scale to basically let the scaling
  • 00:35:21 function know how many data points we
  • 00:35:23 have and we do that by using our dummy
  • 00:35:26 data here and then by calling map on
  • 00:35:29 this and for every data point we get out
  • 00:35:32 of there we can just access the region
  • 00:35:35 field and that basically means we have
  • 00:35:37 now an array full of strings which now
  • 00:35:40 is that array of unique data points we
  • 00:35:42 need here for domain so that the scaling
  • 00:35:44 function knows how many items we'll have
  • 00:35:46 in total we do that and reload now at
  • 00:35:49 least the width is correct they're still
  • 00:35:51 all on top of each other but now every
  • 00:35:53 bar has a width that is small enough
  • 00:35:56 cube theoretically fit for bars next to
  • 00:35:59 each other into our chart however of
  • 00:36:01 course they should be next to each other
  • 00:36:03 and not on top of each other so to
  • 00:36:05 ensure that we now don't just need to
  • 00:36:07 set the width and the height but also
  • 00:36:10 the X and the y attribute which we can
  • 00:36:17 do on SVG elements like our rectangle
  • 00:36:20 and we again set x and y with help of
  • 00:36:24 our scaling functions so here we again
  • 00:36:27 pass in the function so that we get
  • 00:36:29 access to the data point for which this
  • 00:36:30 rectangle was rendered and for X I want
  • 00:36:34 to call X scale and fit in data region
  • 00:36:37 because I used my regions here as my
  • 00:36:41 domain for the X scale so d3.js is aware
  • 00:36:45 of the
  • 00:36:45 for region names here and now by passing
  • 00:36:50 in our region here again it knows which
  • 00:36:52 data point it is for which it should
  • 00:36:54 position the item and it automatically
  • 00:36:56 will position it correctly along this
  • 00:36:59 available range here and we do something
  • 00:37:03 similar for Y there I pass in my data
  • 00:37:07 and I call Y scale here and pass in data
  • 00:37:11 dot value so that it knows where to
  • 00:37:14 position this on the y axis and if we
  • 00:37:17 now reload this looks interesting but
  • 00:37:20 now at least we see four different bars
  • 00:37:23 now why does this look interesting here
  • 00:37:25 it looks the way it looks like because
  • 00:37:28 our height is actually calculated
  • 00:37:30 incorrectly if we change our height here
  • 00:37:33 to be the maximum available height so
  • 00:37:36 200 in our case here minus the
  • 00:37:40 calculated y scale value now it looks
  • 00:37:44 the way it should look like and the
  • 00:37:46 reason why we have to do this is simply
  • 00:37:49 that by default the coordinate system
  • 00:37:51 for D free does not start in the bottom
  • 00:37:53 left corner but in the top left corner
  • 00:37:56 so therefore everything is calculated
  • 00:37:58 from the top left and that means that
  • 00:38:02 since we start at the top and not at the
  • 00:38:04 bottom we calculate the actual height by
  • 00:38:06 taking our max height and reducing it by
  • 00:38:10 that calculated value here on the y
  • 00:38:12 scale so with that we now got a nicer
  • 00:38:16 bar chart here with d3.js now especially
  • 00:38:20 that scaling thing is definitely
  • 00:38:22 something you need to get used to but
  • 00:38:25 here practice is everything the more you
  • 00:38:27 work with that the more charts you build
  • 00:38:29 the easier it gets and in the end what
  • 00:38:32 you learned here about x and y scale and
  • 00:38:34 this code you see here that already is
  • 00:38:36 some code you're going to use a lot you
  • 00:38:38 also of course have to get up repository
  • 00:38:41 of the d free scale package where you
  • 00:38:43 can dive deeper and learn all about the
  • 00:38:45 different scales you have there and how
  • 00:38:47 to use them to understand is positioning
  • 00:38:50 better you can also simply manipulate
  • 00:38:52 those values here so as i said we start
  • 00:38:55 on the top left corner and the y scale
  • 00:38:58 function for it
  • 00:38:59 but simply gives us the y-axis position
  • 00:39:02 off this rectangle here and it takes the
  • 00:39:07 concrete value into account to give us
  • 00:39:09 the right position in relation to the
  • 00:39:11 other elements that are being rendered
  • 00:39:13 so for example here this first bar the
  • 00:39:16 leftmost one which is for the USA has a
  • 00:39:19 y-value of 66.6 six six six six and so
  • 00:39:23 on if we set this to zero here in the
  • 00:39:25 dev tools you see it's all the way at
  • 00:39:27 the top which basically proves the point
  • 00:39:30 that we will start in the top left
  • 00:39:32 corner x0 y0 would be exactly in the top
  • 00:39:36 left corner now we had x8 here because
  • 00:39:41 of the extra padding that was set up and
  • 00:39:43 that's all taken into account
  • 00:39:44 automatically by D free J s and we had Y
  • 00:39:48 is 66 and so on because of the Y
  • 00:39:50 position we derived based on the value
  • 00:39:53 now that shows you why of course have to
  • 00:39:56 calculate a height by deducting that
  • 00:39:58 from the available height because then
  • 00:40:01 you basically render a rectangle which
  • 00:40:03 has a height of 200 minus the space that
  • 00:40:06 should be empty because it's the space
  • 00:40:08 from the y-axis at the top to the
  • 00:40:11 beginning of the bar if we look at it
  • 00:40:13 from the top
  • 00:40:14 so this empty space here that should
  • 00:40:17 stay empty and that is the distance
  • 00:40:18 between the top which is zero and the
  • 00:40:21 starting point of our rectangle which is
  • 00:40:23 66.6 666 ends on so Y scale and X scale
  • 00:40:28 if you call them those functions don't
  • 00:40:31 calculate widths or Heights they
  • 00:40:34 actually just calculate positions inside
  • 00:40:37 of that coordinate system d3.js uses
  • 00:40:39 behind the scenes and it's set up to you
  • 00:40:42 to translate these positions into for
  • 00:40:45 example a height as we're doing it here
  • 00:40:46 now for the width we have this bandwidth
  • 00:40:49 function which we can call on X scale to
  • 00:40:52 get this equal width for all the bars
  • 00:40:54 but for the height we take the position
  • 00:40:56 from the top and deduct this from our
  • 00:40:59 total height which we have available to
  • 00:41:02 get the height of the bar we want to
  • 00:41:05 have from bottom to the top so once you
  • 00:41:08 think about it like this this also
  • 00:41:10 shouldn't be too mysterious and hard to
  • 00:41:12 grasp
  • 00:41:12 now with that of course there's more you
  • 00:41:15 can do you could add an axis you could
  • 00:41:17 do other things but I'll leave it there
  • 00:41:19 for now was long video already I hope I
  • 00:41:22 at least could get you started with
  • 00:41:24 d3.js and explain roughly what it does
  • 00:41:28 and what difference is to jQuery and so
  • 00:41:30 on are and that it's not just for charts
  • 00:41:32 and I hope that this basic functionality
  • 00:41:35 is clear now there is just one thing
  • 00:41:37 which I also want to dive in before I
  • 00:41:39 really finish the video and that's that
  • 00:41:41 select all thing here which I did before
  • 00:41:43 I added data I mentioned that I do this
  • 00:41:46 even if nothing was rendered before and
  • 00:41:48 the reason for dad is actually that we
  • 00:41:51 now bound data to those bars and yes
  • 00:41:54 initially we have no such bars but that
  • 00:41:56 changes once such bars were rendered and
  • 00:41:59 you can see the effect of that if you
  • 00:42:02 actually add let's say a set timeout
  • 00:42:05 function down there where you set a
  • 00:42:08 timer of let's say two seconds to then
  • 00:42:14 execute this function and in there I'm
  • 00:42:18 going to use my bars here the bars which
  • 00:42:22 were rendered here and I'll set my bars
  • 00:42:26 to some new data which is let's say my
  • 00:42:29 dummy data but with the slice data I'm
  • 00:42:32 only going to take a part of it only the
  • 00:42:35 first two items let's say so that it's
  • 00:42:38 not the full array but half the data now
  • 00:42:41 if I do that I can call exit on this and
  • 00:42:44 exit is basically the opposite to enter
  • 00:42:47 enter gave me all the missing elements
  • 00:42:50 which were not rendered yet exit gives
  • 00:42:53 me all the elements that are too much
  • 00:42:55 that should be removed based on the new
  • 00:42:58 data I'm feeding in and it's not taking
  • 00:43:00 any elements that are too much it's
  • 00:43:03 looking at with which data the elements
  • 00:43:05 were rendered and which data is still
  • 00:43:07 there and just give me the elements that
  • 00:43:09 were rendered but for which the data is
  • 00:43:12 not there anymore
  • 00:43:13 and then we can call remove on that
  • 00:43:15 selection to remove all those elements
  • 00:43:18 from the DOM
  • 00:43:21 and with this if we save this and reload
  • 00:43:24 you will see that after two seconds the
  • 00:43:26 last two bars disappeared because
  • 00:43:29 they're not part of the rendered data
  • 00:43:30 anymore and this shows why we have to
  • 00:43:33 select bars here I'm using bars which is
  • 00:43:36 this constant which is this entire
  • 00:43:37 selection which in the end are the
  • 00:43:39 rendered bars but if I wouldn't select
  • 00:43:41 bars here this would not work if I would
  • 00:43:44 remove that code
  • 00:43:46 nothing would actually work here it
  • 00:43:48 wouldn't be rendered at all and the
  • 00:43:51 reason for that is that the free choice
  • 00:43:52 would not work which concrete elements
  • 00:43:55 even if they're not yet on the Dom will
  • 00:43:59 be tied to the data it's not the
  • 00:44:01 container that's tied to the data the
  • 00:44:03 elements inside of the container are
  • 00:44:05 connected to the data instead that's
  • 00:44:08 what we have to select them even if
  • 00:44:10 they're not there yet so that the
  • 00:44:12 freezer has knows which values will
  • 00:44:15 eventually be there because it can only
  • 00:44:17 tell me which data is missing or too
  • 00:44:20 much if it knows which data should be
  • 00:44:23 there so which elements it should find
  • 00:44:25 and if we just say hey have a look at
  • 00:44:28 the container well we do have one
  • 00:44:30 container here we then try to render
  • 00:44:33 more rectangles based on missing data
  • 00:44:35 but the container is no such rectangle