Video Summary and Transcription
Ido, a full stack developer, discusses the benefits of building data visualization components from scratch using React, SVG, and minimal D3. Understanding basic SVG shapes, group elements, and SVG's declarative nature. Exploring SVG's compatibility with CSS, DOM events, and browser features. Highlighting pitfalls in integrating D3 with React and separating data transformation utilities. Utilizing D3 libraries for data manipulation and creating Sparkline components. Enhancing components with markers, CSS styling, interactivity, transitions, and pie charts. Utilizing CSS for animations in data visualization and gauge visualization with needle animation. Defining SVG components, interactions, and considerations for DIY vs. library integration. Exploring D3 axis, AG charts, and time-based animation.
1. Benefits of Building Data Visualization Components
Ido, a full stack developer, discusses the benefits of building data visualization components from scratch using React, SVG, and minimal D3. By avoiding heavy libraries, developers gain control over structure, style, and integration, reducing bundle weight and cognitive overhead. Custom solutions tailored to specific use cases are emphasized, highlighting the efficiency of self-built components.
Thank you. Hi, everyone. Hope you're having a great time. My name is Ido. And as the intro already said, I'm a full stack developer with over a decade of experience working mostly in start-ups. These days I'm working at agigrid where I'm working on our charting tools, agicharts, complete visualization and community packages. But today I'm not here to talk about agicharts, I'm here to talk about simplicity. And why actually there are some cases when you don't need to reach out for a library immediately, there's a benefit in building all of these data visualization components for yourself.
So in this talk today, I want to show you what exactly we can achieve by using just React and SVG. We are going to use a touch of D3 which we'll get to in a moment. But no heavy lifting libraries, no data visualization libraries, like we're going to use D3 as a utility library actually, and I'm going to let him do the hard work, but let React do the hard work for us. So first of all, why not use a library? You get a lot of benefits from building things by yourself. First of all, you get full control over the structure, the style and behavior of your library, and it gets to work perfectly with your data model, like you can make sure that it works precisely with what is important to you and not support any other mapping or unnecessary features to your specific use case, and other than that, no integration headaches that usually come with adopting a new library.
And that's not even mentioning the traditional downsides of a library that you get every time you adopt no library. You get a lot of benefits from the database, such as the unnecessary bundle weight, which is especially important when we're talking about data visualization tools, which tends to be very heavy, and not a lot of them support tree shaking, and even those that do don't support it very well. And the cognitive overhead that comes from learning a new API or adapting new abstractions to your own abstractions in your code, all of the pre-baked assumptions that come with choosing a library, that at some point, you're going to have to start going through hoops just to try to make things work your way. And generally speaking, it's an overkill for most basic use cases.
2. Building Data Components with React and SVG
Discussing the minimalistic nature of SVG for 2D graphics and the benefits of using React and SVG with a touch of D3 for data visualization. Understanding basic SVG shapes like lines, rectangles, circles, ellipses, polylines, polygons, and paths. Exploring group elements for styling, view box for coordinate system positioning, and SVG's declarative nature that integrates well with React.
Unless you actually need a complete data visualization library, because you need multiple chart types or multiple ways to configure it, theming support and things like that, there's probably an overkill to your use case. So today what we're going to do is we're going to be building a library that will repel data components in React and SVG, as I said, with a little bit of D3, which I'll talk about in a minute.
So first of all, let's demystify SVG a little bit, especially if it's new for you so you'll be able to understand the code examples that we'll go through. SVG is scalable vector graphics, in case you don't know, which is basically a mark-up-based language to describe 2D graphics. The nice thing about SVG is that it's a very, very minimalistic language. Basically, it supports only a handful of shapes. All of them are on the screen right now. So basically, right now, you already know, like, more than 50% of SVG. It's already in your hands.
We have a line, a rectangle, a circle, and an ellipse. We also have a polyline, which is a line composed of multiple points, a polygon, which is basically the same thing. Only the first and last points will connect to create an enclosed shape. And we have our SVG path, which is the most versatile of all of them. We're not going to get into the syntax itself, but basically, it allows you to describe any shape you want using lines and curves. We also have in this example, you can see a group element, which allows us to style multiple shapes at the same time. You can also see the styling itself, which is mostly strokes and fields, the equivalent to borders and backgrounds that we get from HTML. And at the top, I will take one minute to talk about the view box that you can see on the SVG element that basically, the value itself is X, Y, width and height of what is the camera position of our coordinate system.
3. Benefits of SVG and Integration with React
Discussing Cartesian coordinate systems in computer science, utilizing the view box for SVG image scalability, and the benefits of SVG's declarative nature for integration with React. Exploring the differences between canvas and SVG, emphasizing SVG's compatibility with CSS, DOM events, and browser features.
Now, it's worth mentioning that I'm assuming that most of you know the Cartesian coordinate system from math classes, university, whatever. And it usually is presented in a way where the Y axis goes upwards. But in computer science, it's actually at the origin point is usually at the top left corner of the screen with the Y values increasing as we go downwards. Just keep it in mind as we go over the examples, just not to make any confusion, cause any confusions.
We're basically going to use the view box to set the visible region of the canvas, as I said. And the reason to do that is if we want to create a make our SVG image scalable or if we want to reposition the origin point, which again, we'll see in a minute. Why not use canvas anyhow? Well, canvas is a low-level programmatic API that allows you a lot of control over how things are rendered, but it also means that you're losing a lot of the benefits that come with using a browser.
For example, if you want to do accessibility, then you have to write it completely by yourself. If you want to have like a rendering queue to decide when is the right time to render, then it's your responsibility. So basically, what's nice about SVG is that it actually is declarative, which works very well with React and is DOM-based. So most of the things we're used to exist in SVG. It's easier to integrate with both CSS and DOM events. And generally speaking, just leverages from everything that the browser can give us. So most of the API that you're familiar with from a regular DOM, like HTML-based DOM, will also be supported by SVG.
4. Challenges in Integrating D3 with React
Discussing the pitfalls of integrating D3 and React, highlighting the anti-pattern of letting D3 dominate the DOM rendering process instead of leveraging React's strengths. Emphasizing the importance of separating data transformation utilities in D3 from React's rendering capabilities.
Now let's talk a minute about D3. Like most of you probably know D3 is like this charting library that everyone uses or at least like at the base of most libraries, but actually D3 these days is a collection of utilities for working with data. It helps you basically map values into geometry and it offers a lot more than that, which you probably don't really need. And if you want to take it, then it's up to you. But that's not what we're going to talk about on this talk.
So basically, the most common pitfall I see almost everywhere when trying to integrate between D3 and React, it usually starts with a ref on the top. And you can already guess what the final line of the component is going to look like. It's going to be an empty SVG element with just the ref on it. And basically, we gave all of the rendering responsibility to D3. But if that's what we're doing, then what's the point of using React? Like basically we're bypassing React here just to make sure that D3 can act as it wants, pretending that React is not there. Now, it's not the only thing that D3 does here, because we do have like the data mapping itself, the utility's part I was talking about.
But this pattern, I would consider it an anti-pattern. Because basically, the moment you let D3 take over your DOM, it means that React is basically not really doing anything. It just became a wrapper and technically a liability because it makes code harder to test. And it creates very, very nasty side effects when the two systems are acting under the assumption that they are controlling the DOM, and each one of them has very different abstractions to do that. The right way, in my perspective, to do that, to do the integration of D3 and React, would be to separate between the utility part which transforms our data for the rendering, and let React do the rendering itself, which is what React is meant to do.
5. Utilizing D3 Libraries for Data Visualization
Exploring D3's utility library structure and the selection of three essential D3 libraries for data manipulation and visualization. Creating a Sparkline component using D3 array, scale, and shape for data transformation and SVG path creation.
These two examples, the one we saw previously and this one, both generate the exact same chart, and they are completely equivalent, except that one is using D3 to do the rendering and the other one uses React. So what is D3 actually made of? If you can see, this is the index file of D3, and it's basically like 30 tiny packages working together, which means that it really is a utility library and it's very shakable and very functional, which is nice to work with. But from all of these libraries, only six actually rely on the DOM, actually do something that needs the DOM in order to function. Most of the libraries are either for managing shapes or specific types of graphs and charts, or just plain utilities. Like if you notice here, you can see we have a library for doing fetching. We have a library for doing random numbers, which you can just use math random. A lot of these things, like the reason they're there, because D3 wanted to be like the jQuery of data, that you can use that and nothing else in order to represent your data. But when we're using React, it doesn't really align with that, and you don't really need to talk all over it to take with us all of these libraries. So in this talk, we're only going to use three of the D3 libraries. We're going to use D3 array for one method that will help us to get the minimum and maximum values out of our domain. We're going to use D3 scale for functions that will help us make our data values into visual values. And we're going to use D3 shape, which is going to help us with creating those SVG paths for arcs and pies. So let's begin into the actual examples.
The interesting part. What we have here is a Sparkline component. You can see only 25 lines of code. So it's very simple. There's not much going on here. And what is going on here? Basically we're creating a linear scale. We're giving it the domain, which is in this case all of our years. Notice that we're using the extent function. So we're basically giving it an array with our minimum year and maximum year. And as a range, what it's going to cast our value into, we're giving it the X position, like the width of our SVG in this case. We do the same thing exactly with our Y values. This time we map the sales into our height position. Notice that the direction is different between the width and the height, because as we said, like the higher the Y value is, it means that the lower our value should be, because we want it to be at the bottom of the screen and not at the top. Now we take those two scaling functions, we use them together to map all of our data points to X and Y positions, and we just take that, stick it into our polyline that we saw earlier, and basically that's it. We got ourselves a Sparkline. A little bit of styling, but nothing more than that. Now let's do something more with it.
6. Enhancing Sparkline with Markers and CSS Styling
Adding markers to the Sparkline for data representation and utilizing style components for CSS integration with SVG elements.
Let's add markers, for example, so we already have the points. All we have to do is go over our array of points again and this time draw a circle everywhere that we have, everywhere that we want to represent the marker, and that's it. We added another feature to our Sparkline. Let's continue.
In this example, as you can see, first of all, we're using style components, because SVG supports CSS, as we said, you can just give it a class name. In this example, I'm using style component, but you can use whatever you want. You can write plain CSS, you can use CSS models, whatever you prefer.
Notice that style component have absolutely no issue working with SVG elements. You can just tell them I'm working with a circle and then just give it a CSS. More than that, I can style anything with CSS, including things like the radius or if it was a line, like X values, Y values, things like that, because technically those are visual values. Everything on a shape is a visual value.
7. Enhancing SVG Interactivity and Pie Charts with D3
Adding transitions and interactivity to SVG elements, integrating with CSS for tooltips, and creating pie charts with D3 tools.
And we can also add transitions to it, including adding transitions to the radius itself. And I'll show you an example, and you can see that just like that, we added a little bit of interactivity into our chart. Everything is nothing new. Things that you're already used to working with when you work with HTML. So it really is just about being able to read this SVG syntax that, as we said, is very minimalistic, so it's not too much, and you'll be able to do these sort of things yourself.
Matt, let's look at the mouse wasn't supposed to be here, but the main point of this example is basically it works with events and everything that we have in the DOM pretty well. Like, we can just take a tooltip library like Teepee. The only thing I had to do to make it work is include the CSS files, so we'll have some styling for the tooltips. Then it just automatically works because it connects to the regular DOM events that we're used to. In this specific example, just by putting Teepee, I actually got their accessibility support out of the box. I didn't need to do anything. They're automatically putting the ARIA labels for me, and I get accessibility for my SVG chart without lifting a finger.
It's very easy to use SVG and integrate it with everything else, so you don't need to learn new things. It's not a new stack that you need to adopt. It's about being familiar with these specific elements and understanding the little tricks that you need. There's not a lot of heavy lifting here. Let's look at the pie chart example. First, we determine what our radius is by looking at the minimum of the width and height and dividing it by half to fill up as much space as you can. Then, we create an ordinal scale, mapping categories into colors. The functions used are straightforward and shouldn't take longer than 10 lines of code. From the D3 shape package, we use the pie function.
8. D3 Pie Chart Creation and Interactivity
Creating pie charts with D3, utilizing pie function to generate arcs and mapping data for visualization.
So let's look at the logical part. First, we determine what our radius is just by looking at the minimum of the width and height and dividing it by half to fill up as much space as you can. Now, we create an ordinal scale this time. So what happens here is we're basically mapping our categories into the colors. Unlike the linear scale, we're mapping each category into a specific color and the main point of this function is that it will make sure that they get the same color each time for a category. Again, all of these specific D3 tools that I've used, you could have implemented it yourself. It's a bit easier here in the example to just show something that's working. But those are functions that shouldn't take longer than 10 lines of code.
Then we're going to use from the D3 shape package, we're going to use the pie function. That's basically going to create a mapper. In this specific case, we're defining that we don't want to have sorting because it does sort values by default. That's why you can see that the pie chart is nice, like, and not equally divided like each value is in its own place. And we tell it what value to actually look at in order to divide our data into arcs, basically. And then we need to create our arc function in order to actually generate the path for the arc. We're giving it the inner radius of zero and the outer radius of our pie chart. And basically, that's it. We finished with our pie chart. You can see we're putting our data into that pie function, then just mapping it and taking the data object that the mapping function provided for us and just passing that on to the arc function. And basically, we finished. We have ourselves a pie chart.
One thing that I'm going to say here about the transform. We're going to see examples. In future examples, we're going to see where we use the view box, as we said, to reposition our origin point. Here, we use another trick to do basically the same thing because, as you've seen here, there's no actual X and Y value, so how does it know where to end our circle? Basically, it renders it at the origin point, meaning that the center of our pie chart is actually sitting at the top left corner. So in order to push it back into the middle of our canvas, our view box, we're using transform translate just to push it to the middle of the screen. If we want to take this example and just turn it into a donut chart, all we have to do is basically just change the inner radius of our arc function. It will do everything for us. Nothing more than that. Now, let's look about another type of interactivity that we can add. So in this example, what I did is we have ourselves an arc group that takes a CSS variable.
9. Advanced CSS Styling and Gauge Visualization
Utilizing CSS for sleek animations in data visualization components; Overview of gauge visualization with a focus on scale and rendering adjustments.
Again, you can use whatever you're already familiar with working with regular DOM. And we're setting a radius as a CSS variable called arc radius, and inside our group we have one new thing, which is a clip path. That's for masking if you're familiar with the technique. And inside our clip path, we're putting just a circle with no definitions at all, and we're going to attach to our path the clip path, using the ID to tell it this is your clip path. You should mask according to that. And what does the circle actually do? Well, again, we can just style it with CSS. So we give the properties to our group, and we'll see in a minute why. We're styling our circle. We're basically setting our radius to 90% of the actual value of the radius. And we're setting a transition, again, on the radius, with a nice cubic Bezier for a nice animation and easing. And then we're telling it that on a hover of any component, which in this specific case is going to be the path, because the clip path is not actually a visible component. If we're hovering over an element, take the circle and enlarge its radius to its full value. And what we get from that is a very sleek and very simple animation that we didn't have to work hard at all to get to, just by using a little bit of CSS in the ways that we're already familiar with.
Now let's look at one final type of data visualization example. Let's look at gauges. So these are the more complicated types of components. But then again, still you can see we're talking about 31 lines of code that we're going to go over, like, in one minute. So what do we have here? Again, linear scale in all types of data visualization. We're probably going to have some sort of scaling function. This time we want to scale between our domain, which is a value between zero and 100, to a range which is an angle between minus 90 degrees to 90 degrees. That's for the needle of the gauge. Here you can see that we're actually using the view box. And instead of rendering from the X zero Y zero position, we're putting, we're starting to render from minus 100, minus 100. And what basically that means is, I can see it, our origin point actually sits at the center point of the base of our needle. So that means that we don't need any special calculation to determine the origin point pair, whatever it is that we're rendering. We can just assume that everything renders according to our origin point, and build things according to that. So for example, our ticks, the gray lines that we have here, you can see, they're all basically exactly the same line that just goes up exactly above the needle. But then we're mapping over the certain degrees that we want to give it and giving each one of those lines a different angle to get the effect of the ticks all over our arcs. We have an arc. We could have used the arc function from D3 if we were not comfortable with using a path, or just give it to JGPT, we'd also know what to do with it.
10. Needle Animation and Benchmark Gauge Usage
Focus on needle animation, conventional benchmark gauge usage, and arc generator properties for gauge visualization.
And we have our needle, which is the only thing which is actually being animated and directed here. We have a circle in the middle, and on top of that we put a triangle to get this nice visual effect. If you have a designer, you're probably going to get much nicer things out of it, but I didn't have a designer, but it's amazing the things you can just do from wrapping up a bit of code all by yourself.
Let's look at another example, which is basically the same but a little bit different. So another type of gauge, this time we're using the more conventional, like, benchmark gauge. Again, we have the angle scale. This time we decided to take the domain from the properties so the user can define what's the start and end of the domain, and we're casting it into an angle. This time instead of degrees, we're using radians, but basically it's the same thing, between minus 90 degrees to 90 degrees, just in radians.
We're building our arc generator. Notice that we're giving here three properties here, the inner radius, the outer radius, and the start angle. Basically, only thing it needs now in order to generate an arc is the end angle, which is missing. And then we have our actual components. So first of all, you can see on the view box, which is interesting, we're basically drawing a two pixels square. That's because we don't really care about the size of what we are drawing. We're basically just drawing the arc.
11. Defining SVG Components and Interaction Handling
Defining components with gradients and scales, considerations for complex interactions and scaling, transitioning to libraries for advanced features.
So we're defining it as between minus 1, minus 1, at the width of 2 and the height of 1, and then define a gradient that basically goes between minus 1 pixel to 1 pixel, and we scale that up by giving the component itself a width, so everything is going to scale proportionally. We take that, we basically create one gray arc for the filler, for the background, and another one for the filler, which uses our gradient. And you can see that it also uses our linear scale with the value provided by the user, and that's basically it.
Do notice that we're putting the text values outside of SVG, because SVG handles text a little bit differently. Technically, in this case, we could have used the text element of SVG, but why complicate things for ourselves? We can just use what we're already familiar with. If there's some parts which are easier for you to do in HTML, just do it in HTML and merge the two inside your components. Nothing is stopping you.
When this sort of approach doesn't really work that well, when simplicity isn't enough, when performance or scaling starts to become a real issue, whether it's by having dozens of charts on a single page or having a single chart with millions or tens of millions of data points, then probably SVG approach won't do it for you. If interaction starts to get really, really complex, things like annotations or zooming or even smart labeling for unknown data, then probably just go for a library. If you have multiple teams working on it and each one needs another thing, which basically comes along with the other point, it sort of becomes a product all by itself.
12. Deciding Between DIY and Library Integration
Discussing the need for data validation, theming, and configurability before considering library integration. Emphasizing the efficiency of starting with React for data visualization, exploring SVG and React without relying on libraries. Contrasting SVG and canvas-based rendering regarding performance advantages and the need for manual implementation.
You need to do data validation, maybe you need to support some theming in this thing. You need to allow a lot more configurability, then that's a point where also I might have just moved to a library. And if that's the case and you find yourself needing more power, then I would suggest if you need the performance, the scalability, the scale, do consider us. But I would say or any other library that fits your needs. We are basically very scalable, very enterprise-oriented, so if that works for you, then give us a try.
And closing thoughts, the point of this talk basically I just wanted to show you very, very quickly how React is actually charting data visualization is a great way to start playing with SVG and React and get a hang of it. There's a lot that you can do without ever reaching a library, and it really is more efficient and easier in the long run because you don't have to learn new things, you don't have to do excessive research, you don't have to expose yourself to multiple options, and you don't have to go through loops to support abstractions that basically are meant to support multiple use cases that are just not affecting you.
Thank you very much. All of these slides were created in React. All of the code was live. The QR would send you to the repo itself so you can download it, play with it. Thank you. Awesome. You can leave your laptop there. I have a party hat for you. So SVG versus canvas-based rendering, the advantages and the pros and cons, performance advantages on high data volume. So as I said, I think from a performance point of view, you probably always want to go with canvas because it just gives you the control that you're missing with anything else. But the downside of it is that it will force you to implement anything by yourself. You want to have events on a specific canvas path, you have to create something to take care of it. You want to have accessibility, you have to create something yourself to take care of it. So I wouldn't use it unless you actually got to a point where performance is that big of a problem. But if it is, then, yeah, canvas is the way to go.
13. Exploring D3 Axis, AG Charts, and Animation
Discussing headless D3 axis and offering React version, comparing AG charts to other libraries in terms of performance, and addressing time-based animation in gauge examples, along with D3 shakeability.
But if it is, then, yeah, canvas is the way to go. Yeah. Is there a headless alternative to D3 axis? It is so convenient but unfortunately modifies the DOM. Yeah. So actually, come talk to me afterwards when I have my laptop. I have a version of D3 axis written in React that I gave in another talk that I had about a similar subject. So I can just show you and give it to you. I can share with it happily.
How does AG charts compare to other libraries such as recharts, MUI X charts, what are the pros and cons in your opinion? So if I remember correctly, this specific charting library are all canvas based. So on one hand from a React point of view they are much more idiomatic like they actually are components that you put in place. And that's the benefit of being SVG because it's actually DOM based. But it also means that again, like it's a performance issue. So if you actually go to a very, very large scale, it's going to cause issues. Thank you.
Let's do this one. Where did the time-based animation in the gauge examples come from in the code? So come talk to me after this. I had a bonus slide that I wanted to share in case I have time and I didn't. But it was actually in the last slide. Also, you can go check the code. It's exactly about that. Cool. Let's do one more here. Is D3 tree shakeable? Yes. It's very shakeable. Again, it depends on what you take because some of these packages are actually relying on other packages. So you're going to take them with you. But for the most part it's built very, very efficiently and I do recommend using it if you want to play with utilities for creating your own SVGs. Awesome. Thank you so much, Ito.
Comments