Using SVG Gradients and Filters With d3.js
I play around with the d3.js library for a while now and I always thought that stuff like gradients and shadows are not so easy to create with SVG and that it is simply not made for that. The reason for that is, that when I’m browsing through the d3 example gallery there is so much awesome data visulation, but shadows and gradients are not really present. I know, we are inside of the “flat design era” right now, so who should care about that, but I really like shadows, when they are at the correct places. Gradients on the other hand make very often the tiny tiny difference of a good design and a great design.
I started working on a nice design I found at dribbble (I know it’s not pixel perfect) and came to the point to implement some nice d3 animations rather quickly. And here is the final result.
The timeline diagram and the three circles are made in SVG. Both diagram types are supposed by the design to include multiple shadows and gradients. So let’s have a look how that works.
Shadows and gradients are so called graphical objects in terms of SVG. Depending on their type they won’t be rendered. For gradients and filters (shadows are filters basically) is that the case. If you are interested and want to dive more into that, here are the general specs:
The way this works is, that you have to define these elements first and then reference them via id inside of the element you want to use them. Pretty straight forward. The spec recommends that all elements that will be referenced should be defined inside of a defs
element.
So let’s start with that and see some d3 code! :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
Applying a shadow to an element in the world of SVG needs a bit more than doing it CSS, but I have to admit, that the documentation for SVG filters is really good. The W3C provides a lot of example including one for shadows. Developers that are used to work with CSS mostly care only about three parameters – x-offset, y-offset and blur. I marked them inside of the code example.
The fourth parameter that is configurable in CSS is unfortunately not so easy to set. As long we are setting filters to a given element, it seems to me relatively hard to achieve a completely different color as a shadow color – but if anyone knows a way to do that, I would really like to know.
To sum up, what basically happens here are three steps:
- create gaussion blur on alpha channel –
feGaussianBlur
| spec - move result of gaussian blur to wished position –
feOffset
| spec - define output result by merge (original source graphic over result of offset operation)–
feMerge
| spec
And that is the result of the d3 operations inside of the SVG:
1 2 3 4 5 6 7 8 9 10 |
|
And that is it for defining a shadow filter in SVG. After that we only need to reference it inside of our wished elements.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
And here is the result with applied shadow filter to two text
elements and two path
elements:
Gradients are quite similar to achieve. Let us check the needed d3 code to define a gradient element:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Defining of the gradient
element is not as complicated as the filter
element. I decided to use a linearGradient
(spec here). All we have to do is give it an id (we need to reference it later). Per default the linear gradient is a horizontal one. I wanted to have a vertical one and that is why there are coordinates set inside of the code example. The coordinates describe a vector which represents the gradient.
By appending two stop
elements we are able to define which color should be set where. This gradient is a really basic one defining colours from start to end point. Much more complicated things are possible and Mozilla has a few really good examples at MDN.
And that is the result of the d3 operations inside of the SVG:
1 2 3 4 5 6 |
|
The nice thing about gradients is, that it is possible to define the colors inside of a stylesheet. I really like that, because everything related to colours belongs exactly there. That makes the whole thing much better maintainable.
The stop
points for the gradient include the class elements, which I can reference inside of my stylesheet (I prefer using Compass by the way).
1 2 3 4 5 6 |
|
The last step is to set the gradient to the wished element. This is done by referencing it inside of the stylesheet by its id.
1 2 3 4 |
|
And here is the result:
And that’s it. If you want to play around with it check out the pen ad Codepen. Feedback is as always welcome and I hope you have as much fun playin around with d3 as I have. :)