In Part 1 of this series on re-creating the Ruder-Finn Intent Index radial bar chart using D3.js, I created the background and the category gridlines for the chart, and in Part 2, I added the question gridlines and bars. In this last part of this three part series, I add the category and question labels to the chart.
Working with the category labels was fairly straightforward, especially after reading the fantastic tutorial, Placing Texts on Arcs with D3.js. This tutorial contained the solution for putting the labels on the arc and flipping the labels on the bottom half of the chart so that they weren't upside down. I added the requirement that the whole slice (not just the end angle) had to be between 90 and 270 degrees before flipping the label. This coincidentally resulted in all of the questions labels being flipped for a flipped category label, however a better solution would have been to only flip the question label if the category label was flipped.
The question labels were more complicated to deal with because they had to additionally be wrapped and centered both horizontally and vertically.
For wrapping the text, Mike Bostock's Wrapping Long Labels gave me a start to my solution. The function he provides ended up working well once I realized I had to determine the length of the arc and the length of the label in a less elegant manner. The result is the wrapTextOnArc function, which could use some refactoring, but gets the job done. The trick here was to create a temporary text element for use in getting an accurate measurement of the text length because using getComputedTextLength on the tspan's node just wasn't working (presumably because it was on an arc). This allowed me to determine when to wrap the text as well as assign an x value to the tspan in order to horizontally center each line.
After wrapping and horizontally centering the question label, I had to make one more pass against the question labels to vertically center them. This basically consisted of a trial and error adjustment to the dy attribute of the first line (i.e. tspan) of the label based on the number of lines.
Working with the category labels was fairly straightforward, especially after reading the fantastic tutorial, Placing Texts on Arcs with D3.js. This tutorial contained the solution for putting the labels on the arc and flipping the labels on the bottom half of the chart so that they weren't upside down. I added the requirement that the whole slice (not just the end angle) had to be between 90 and 270 degrees before flipping the label. This coincidentally resulted in all of the questions labels being flipped for a flipped category label, however a better solution would have been to only flip the question label if the category label was flipped.
The question labels were more complicated to deal with because they had to additionally be wrapped and centered both horizontally and vertically.
Why People Go Online - Ruder Finn Intent Index |
For wrapping the text, Mike Bostock's Wrapping Long Labels gave me a start to my solution. The function he provides ended up working well once I realized I had to determine the length of the arc and the length of the label in a less elegant manner. The result is the wrapTextOnArc function, which could use some refactoring, but gets the job done. The trick here was to create a temporary text element for use in getting an accurate measurement of the text length because using getComputedTextLength on the tspan's node just wasn't working (presumably because it was on an arc). This allowed me to determine when to wrap the text as well as assign an x value to the tspan in order to horizontally center each line.
After wrapping and horizontally centering the question label, I had to make one more pass against the question labels to vertically center them. This basically consisted of a trial and error adjustment to the dy attribute of the first line (i.e. tspan) of the label based on the number of lines.
While not resulting in an exact replica, its pretty close. I ended up making some adjustments to the code in Plunker in order to make the chart fit within my blog post. This meant shrinking the chart and shrinking the font so that the word "Community" would fit.
There's a lot of room for improvement here, including: choosing a better font; sizing a label's font if it contains a word that is too large for the allotted space (e.g.: community); flipping a question's text only if the category's label was flipped; only flipping the category label if the majority of the arc is on the bottom half; and adding more chart animation and interactivity.
However, in the end, I still feel like I accomplished my goal of establishing a jumping off point for creating a chart that will better fit my own data.
For a complete listing of the code and a working example, check out the Plunker:
Thanks for sharing!
ReplyDeleteHi Ken: Are you available for hire to create a slightly modified version of this chart? Essentially, trying to add a second set of values that would overlay a line on the bars (1 arc for each bar representing the group average score). thanks!
ReplyDeleteHi Doug,
DeleteI wish I had more time to work on improving this code and the chart's capabilities. I did, however, throw together a quick solution (i.e. hack) for adding the arc averages to each category. Hopefully its what you're looking for or, at least, points you in the right direction:
https://plnkr.co/edit/IB8KOwfrGQVHsEyJsMxO?p=preview
Hey Ken: Awesome - thank you! I'll look for a d3 coder to help with some other tweaks.
ReplyDeleteNice Work, congrats!
ReplyDeleteit's possible to customize with different color each bar?
thanks
Hi Ken,
ReplyDeleteit's possible to customize with different color each bar based on category_label?
Thanks,
Prajeesh
This is amazing. Thank you for your contribution. Could you please advise if there is a way to display multiple data points that may be collected thru a CSV file and show the median or mean thru the color indicator?
ReplyDeleteHi Ken,
ReplyDeletegreat work!
How do we add another Label to the arc like say : top_category_label, Category_label, question_label,value.
thanks in advance :) waiting for your leads
I want to export this diagram in a word file (the text should be vector). Can anyone help me?
ReplyDelete