A different look for the D3 radar chart

Redesigning the version from 2 years ago

Posted: October 19, 2015-Likes: 1-Comments: 26-Categories: D3.js, Interactive, Tutorial-Tags: D3.js, Data Visualization, Radar chart
You are here: ...
Home / Blog / D3.js / A different look for the D3 radar chart

A bit more than 2 years ago I wrote a small blog about making the D3 radar chart look a little better. I know that opinions are diverse about the usefulness of these types of charts. But I can’t deny that I personally have a love for circular charts, I’m sorry. I even keep a Pinterest board specifically for circular data visualizations :)

Since that chart in the blog from over 2 years ago I haven’t created another radar chart actually, until a small project came by right before the start of the summer.

So I went back to the code from my blog (originally from alangrafu which I only adjusted a bit for better esthetics) to set-up a new radar chart. One good thing, after 2 years of D3 & JavaScript I finally understood what each line did :)

Slowly I started to change things to the code, because I wanted a different look, but also to simplify the code, use different functions or different SVG elements. In the end I ended up with a new radarChart function that probably only contains 10% of the original code and that looks rather different (as you can see below).

The two biggest appearance changes are a circular grid in the background, adding the option to choose smooth connecting lines and adding an SVG glow filter around the stroke (I just liked the look. I’ll write a different blog about SVG filters and gradients in D3.js later)

Previous Design
New Design

Some ideas are still the same. The mouse over interactivity that highlights one shape and dims all others, the small tooltip that appears when you hover over a circle to see the exact percentage and the way the function gets called and how you supply the possible options.

However, some of these options have changed. The ones currently available (shown together with their default values) are:

 w: 600,				//Width of the circle
 h: 600,				//Height of the circle
 margin: {top: 20, right: 20, bottom: 20, left: 20}, //The margins of the SVG
 levels: 3,				//How many levels or inner circles should be drawn
 maxValue: 0, 			//What is the value that the biggest circle will represent
 labelFactor: 1.25, 	//How much farther than the radius of the outer circle should the labels be placed
 wrapWidth: 60, 		//The number of pixels after which a label needs to be given a new line
 opacityArea: 0.35, 	//The opacity of the area of the blob
 dotRadius: 4, 			//The size of the colored circles of each blog
 opacityCircles: 0.1, 	//The opacity of the circles of each blob
 strokeWidth: 2, 		//The width of the stroke around each blob
 roundStrokes: false,	//If true the area and stroke will follow a round path (cardinal-closed)
 color: d3.scale.category10()	//Color function

You can set the options that you want and call the function in radarChart.js with the following code (which are the options I used for the images in this blog):

var color = d3.scale.ordinal().range(["#EDC951","#CC333F","#00A0B0"]);
var radarChartOptions = {
  w: width,
  h: height,
  margin: margin,
  maxValue: 0.5,
  levels: 5,
  roundStrokes: true,
  color: color
//Call function to draw the Radar chart
//RadarChart("id or class of to which the new SVG needs to be appended", the dataset, the options (optional))
RadarChart(".radarChart", data, radarChartOptions);

A hover highlights the chosen element

The Code

One of the things that I hope the new radarChart function offers is better readability. That you can more easily understand what is happening. So if you want to make adjustments that are not part of the current option set, you are able to adjust the code of the radarChart function without to much difficulty.

You can find the interactive version of the radar chart images above here and the code for the new radarChart.js function here

You’ll still have to make your own legend ;)
(PS: The data in this one represents reasons current users of the iPhone, Samsung or Nokia smartphone find important in choosing their next phone in the Netherlands, taken from the last year’s Global Mobile Consumer Survey (2014) performed yearly by Deloitte)

Prev / Next Post
Comments (26)
  • @micahstubbs - October 19, 2015 - Reply

    I really like the thorough comments in the code, as well as the other block credited in the helper function. +100 :-)

  • @micahstubbs - October 19, 2015 - Reply

    a small iteration to handle nested data. may be nice to have the key names accessible when I create my legend :-)


  • @micahstubbs - October 19, 2015 - Reply

    another iteration – radar chart with smallest area on top http://bl.ocks.org/micahstubbs/465725cdc547c7cc8491

  • Charles Allen - October 20, 2015 - Reply

    Awesome! I started with your last version when I built the Radar Charts for TAVA and I would love to update the look for my next release. One thing I added was support for diverse types of axes, a la parallel coordinates. Would love to see this as a standard feature of your radarChart.js


  • @micahstubbs - October 20, 2015 - Reply

    made my own legend! I’m not sure if putting the legend inside of RadarChart() is the most elegant solution, but its nice to be able to access the color scale.


    • Nadieh
      (Author) Nadieh - October 21, 2015 - Reply

      Wow, really cool! Very useful additions, thank you for making them (and in, like, a day no less) +1000

    • @TennisVisuals - November 24, 2015 - Reply


      I incorporated your modifications into my re-write of radarChart (smallest area on top)… and provided hooks such that external components such as legends can be driven by radarChart events, all configurable in the options.


      – Charles

  • Ella S - October 23, 2015 - Reply

    Hey I was working with your code, and it looks really great! However I think you may have made a small mistake because right now your chart will only draw correctly with 8 axes. When you’re appending the lines you should be using the same code to determine x2 and y2 as when you determine the label axes’ x and y. Thanks for putting this out there, it is the best radar chart I’ve worked with!

    • Nadieh
      (Author) Nadieh - October 27, 2015 - Reply

      Thank you! And you’re absolutely right, that was a silly mistake in the code. Thank you for pointing it out, I’ve fixed it now :)

  • Brian Booden - October 26, 2015 - Reply

    Hey Nadieh, i implemented your example into Qlik Sense and am working with one of my colleagues to make this a fully configurable, breathing thing in Sense, with all of the appropriate properties exposed.

    It’s here on GitHub: https://github.com/brianbooden/D3ImprovedRadarChart

    Will let you know when it moves past prototype stage!

  • Ryan Chase - November 4, 2015 - Reply

    This is great! Thanks for sharing the updated version. One question, is it possible to use a polygon instead of circles for the grid?

    • Nadieh
      (Author) Nadieh - November 4, 2015 - Reply

      Hi Ryan,

      It’s not one of the pre-made options, sorry. But you can try to adjust the code (lines 80 – 90) to replace the circles with polygons

  • Jon Peltier - December 3, 2015 - Reply

    It’s still a radar chart, so not much progress was made. Why not use parallel coordinates?

  • Simon - December 21, 2015 - Reply

    What is the license for this code? Is it allowed to use this in a commercial product?

  • Aldo - February 5, 2016 - Reply

    Hi there, first of all, this radar chart is awesome, thanks for sharing. Just one question, is it possible to apply animation to the blobs in case I add a couple of radio buttons to display different data, sorry I’m new with D3 and I struggle with transitions but I would like to implement it since it would look fantastic! any recommendations?

    Thanks in advance!

    • Nadieh
      (Author) Nadieh - April 22, 2016 - Reply

      Hi Aldo, thank you, I’m glad you like it! In theory adding an animation would indeed be possible, but then you’d have to make adjustments to the radar chart code itself. Right now it just deletes whatever was there before, but for an animation between datasets it should comply with the update-enter-exit method of D3. Here is a good example of how to implement it: http://bl.ocks.org/mbostock/3808234

  • Rakesh - May 2, 2016 - Reply

    Is there any way to build all Y- axis with different max value and different unit, like one max is 2000 and levels are $500, $1000 , $1500 and $2000 and other one like Max is 8 and levels are 2, 4, 6, 8 something like this.

    • Peter Andrews - September 22, 2016 - Reply

      I created a separate linear scale for each axis with the domain being the [axisMinimum, axisMaximum] and the range being 0 to 1 thereby and showed all axes as percent of possible for that axis. You can either store the scale in the axis and use it for all points on that axis or scale each point ahead of time.

  • Lalit Maurya - May 14, 2016 - Reply

    Hi, how can we handle negative values like -0.45 or -87

  • Haneen - July 25, 2016 - Reply

    Thank you very much for a beautiful chart.. I have a question if you may, how can I make the chart responsive? I am expecting users to visit my site on their phones and I want the chart to resize for smaller displays.

  • aalokit - January 31, 2017 - Reply

    Hi want the chart to be unfilled, ie only the boundries to be colored, rest of the chart not to be colored. how can i do so. please help asap

    example to support my question : http://jsfiddle.net/5gHVY/143/

  • Pedro Francisco - March 3, 2017 - Reply

    Hi, great article!
    But I was wondering: if I wanted the scale of the values to go from 10 to 20, how would I proceed?

    For instance in this article the circles go from 0% to 50%, but I wanted my scale to go from 10 to 20.

  • elmario - November 8, 2017 - Reply

    First of all – thank you, this is great and I’m using your code in my project.
    Second – sorry for my bad English, I hope you’ll understand me.

    So I’ve got a question: the graphs are stretching by the most biggest value. In your case it is the yellow graph and “To be a smartphone” point, and all other points stretching is calculated by this yellow point value, what if I want my values to be calculated with relying on 100% percent?

    For example – in this case and with your graph – the yellow point should take 50% from 100% width, and all other points rely on 100% either, so no point should be at the edge of the last outer circle, but if you add 100% to the “Large screen” for red graph it WILL be at the edge.

    Maybe there is an option to reach this behaving?

    • elmario - November 10, 2017 - Reply

      Seems like I did it myself.
      So if anyone wondering about this either, you should change var rScale = d3.scale.linear().domain([0, whatEverYouVeGotHere]) value to var rScale = d3.scale.linear().domain([0,1]) (1 here is the most biggest value allowed, so if your graph has values from 0 to 100 you should add 100, not 1)

  • Nikos - November 28, 2017 - Reply

    Could you add the chart to npm?

  • arthur - January 13, 2018 - Reply

    Is there a way to use a different maxVale for each axes? It’s been a lot of time but can’t find a working solution for that.


Add comment

5 × five =