Radar charts have a drawback: there’s a suggestion that values are represented by the area within the line that connects data points. The radial lollipop chart solves that problem. Read the story behind the radial lollipop chart here.
Radial lollipop chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
height: 620 | |
scrolling: no | |
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var data = {"fiets": [{"location": "Ndsm-pont", "1980": 0.0, "2009": 1732.0}, {"location": "Buiksloterweg", "1980": 2207.0, "2009": 8142.0}, {"location": "Adelaarsweg", "1980": 689.0, "2009": 2979.0}, {"location": "Piet Heinkade", "1980": 492.0, "2009": 5742.0}, {"location": "IJtunnel", "1980": 0.0, "2009": 0.0}, {"location": "Mariniersplein", "1980": 281.0, "2009": 1572.0}, {"location": "Czaar Peterstraat", "1980": 239.0, "2009": 4189.0}, {"location": "Borneolaan", "1980": 0.0, "2009": 882.0}, {"location": "Cruquiuskade", "1980": 151.0, "2009": 2051.5355278143275}, {"location": "Zeeburgerpad", "1980": 302.0, "2009": 1239.0}, {"location": "Zeeburgerstr.", "1980": 2900.0, "2009": 5951.0}, {"location": "Alexanderplein", "1980": 4837.0, "2009": 9593.0}, {"location": "Krt. 's-Graves.str.", "1980": 1863.0, "2009": 4224.0}, {"location": "Spinozastraat", "1980": 374.0, "2009": 585.0}, {"location": "Weesperplein", "1980": 2597.0, "2009": 5953.0}, {"location": "Prof. Tulpplein", "1980": 3628.0, "2009": 8840.0}, {"location": "Oosteinde", "1980": 1322.0, "2009": 2764.0}, {"location": "Westeinde", "1980": 5093.0, "2009": 7282.0}, {"location": "Weteringlaan", "1980": 9514.0, "2009": 14956.0}, {"location": "Museumbrug", "1980": 11864.0, "2009": 12672.0}, {"location": "Max Euweplein", "1980": 0.0, "2009": 4600.0}, {"location": "Leidseplein", "1980": 6061.0, "2009": 9160.0}, {"location": "Nwe.Passeerdersstr.", "1980": 2741.0, "2009": 5097.858445317233}, {"location": "Elandsgracht", "1980": 6602.0, "2009": 11273.0}, {"location": "Rozengracht", "1980": 6405.0, "2009": 8450.0}, {"location": "2e Hugo de Grootstr.", "1980": 4586.0, "2009": 8117.0}, {"location": "Marnixplein", "1980": 2681.0, "2009": 4719.0}, {"location": "1e Marnixplants.", "1980": 1264.0, "2009": 2481.0}, {"location": "Haarlemmerplein", "1980": 3587.0, "2009": 10353.0}, {"location": "Van Diemenstraat", "1980": 833.0, "2009": 2903.681545472612}], "auto": [{"location": "Ndsm-pont", "1980": 0.0, "2009": 0.0}, {"location": "Buiksloterweg", "1980": 0.0, "2009": 0.0}, {"location": "Adelaarsweg", "1980": 215.0, "2009": 0.0}, {"location": "Piet Heinkade", "1980": 9874.0, "2009": 13816.0}, {"location": "IJtunnel", "1980": 40717.0, "2009": 26991.0}, {"location": "Mariniersplein", "1980": 7940.0, "2009": 7199.0}, {"location": "Czaar Peterstraat", "1980": 3094.0, "2009": 0.0}, {"location": "Borneolaan", "1980": 0.0, "2009": 3998.0}, {"location": "Cruquiuskade", "1980": 3711.0, "2009": 2922.0}, {"location": "Zeeburgerpad", "1980": 1353.0, "2009": 777.0}, {"location": "Zeeburgerstr.", "1980": 13093.0, "2009": 7009.0}, {"location": "Alexanderplein", "1980": 6068.0, "2009": 3748.0}, {"location": "Krt. 's-Graves.str.", "1980": 7744.0, "2009": 2440.0}, {"location": "Spinozastraat", "1980": 0.0, "2009": 0.0}, {"location": "Weesperplein", "1980": 26256.0, "2009": 21160.0}, {"location": "Prof. Tulpplein", "1980": 0.0, "2009": 2.0}, {"location": "Oosteinde", "1980": 3316.0, "2009": 1202.0}, {"location": "Westeinde", "1980": 16434.0, "2009": 7076.0}, {"location": "Weteringlaan", "1980": 12999.0, "2009": 6506.0}, {"location": "Museumbrug", "1980": 7148.0, "2009": 3246.0}, {"location": "Max Euweplein", "1980": 0.0, "2009": 7.0}, {"location": "Leidseplein", "1980": 6360.0, "2009": 3775.084095992781}, {"location": "Nwe.Passeerdersstr.", "1980": 3509.0, "2009": 1474.7951658918582}, {"location": "Elandsgracht", "1980": 7806.0, "2009": 4685.0}, {"location": "Rozengracht", "1980": 13929.0, "2009": 8119.0}, {"location": "2e Hugo de Grootstr.", "1980": 7920.0, "2009": 4385.0}, {"location": "Marnixplein", "1980": 6792.0, "2009": 3158.0}, {"location": "1e Marnixplants.", "1980": 90.0, "2009": 0.0}, {"location": "Haarlemmerplein", "1980": 16060.0, "2009": 9804.287365883474}, {"location": "Van Diemenstraat", "1980": 14940.0, "2009": 12076.214029503493}]}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Radial lollipop chart</title> | |
<link rel="stylesheet" type="text/css" href="style.css"> | |
<script src="https://d3js.org/d3.v4.0.0-rc.2.min.js"></script> | |
<script src="data.js"></script> | |
</head> | |
<body> | |
<div id="chart"></div> | |
</body> | |
<script> | |
// settings | |
var max = 15000; | |
var subset = 'fiets'; | |
var ticks = 5; | |
var rotate = -1; | |
data = data[subset]; | |
var margin = {top: 50, right: 50, bottom: 50, left: 50}, | |
width = 500, | |
height = 500; | |
var radius = 200; | |
var svg = d3.select('#chart').append('svg') | |
.attr('width', width + margin.left + margin.right) | |
.attr('height', height + margin.top + margin.bottom) | |
.append('g') | |
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); | |
var center_x = height / 2; | |
var center_y = width / 2; | |
function rotated(i){ | |
var rotated_i = parseInt(i) + rotate; | |
if(rotated_i >= data.length){ | |
rotated_i = i - data.length; | |
} | |
else if(rotated_i < 0) { | |
rotated_i = data.length - 1 + parseInt(i); | |
} | |
return rotated_i | |
} | |
function to_radian(i){ | |
return i * 2 * Math.PI / data.length; | |
} | |
function get_xy(value, index){ | |
var length = radius * value / max; | |
y = center_y - length * Math.cos(to_radian(rotated(index))); | |
x = center_x + length * Math.sin(to_radian(rotated(index))); | |
return [x, y]; | |
} | |
function get_anchor(i){ | |
if(rotated(i) == 0 | rotated(i) == data.length / 2){ | |
return 'middle'; | |
} | |
else if(rotated(i) < data.length / 2){ | |
return 'start'; | |
} | |
else{ | |
return 'end'; | |
} | |
} | |
function get_dy(index){ | |
var dy = -3 * Math.cos(to_radian(rotated(index))); | |
dy += 3; | |
if(rotated(index) == 0){ | |
dy -= 4; | |
} | |
return dy; | |
} | |
for(tick = 1; tick <= ticks; tick++) { | |
var value = max * tick / ticks; | |
var plabel = get_xy(value, 1); | |
console.log(value, plabel) | |
svg.append('text') | |
.attr('x', plabel[0]) | |
.attr('y', plabel[1]) | |
.attr('dx', 2) | |
.attr('class', 'label') | |
.text(value); | |
} | |
for(i in data){ | |
var item = data[i]; | |
for(tick = 1; tick <= ticks; tick++){ | |
var value = max * tick / ticks; | |
var start = get_xy(value, i); | |
var end = get_xy(value, parseInt(i) + 1); | |
svg.append('line') | |
.attr('x1', start[0]) | |
.attr('y1', start[1]) | |
.attr('x2', end[0]) | |
.attr('y2', end[1]) | |
.style('stroke', 'grey') | |
.style('stroke-width', 0.5); | |
} | |
var p1980 = get_xy(item[1980], i); | |
var p2009 = get_xy(item[2009], i); | |
var end = get_xy(max, i); | |
svg.append('line') | |
.attr('x1', center_x) | |
.attr('y1', center_y) | |
.attr('x2', end[0]) | |
.attr('y2', end[1]) | |
.style('stroke', 'grey') | |
.style('stroke-width', 0.5); | |
var highest_value = Math.max(item[1980], item[2009]); | |
var lowest_value = Math.min(item[1980], item[2009]); | |
if(lowest_value > max){ | |
start = get_xy(max, i); | |
end = get_xy(highest_value, i); | |
svg.append('line') | |
.attr('x1', start[0]) | |
.attr('y1', start[1]) | |
.attr('x2', end[0]) | |
.attr('y2', end[1]) | |
.style('stroke', 'grey') | |
.style('stroke-width', 0.5) | |
.style("stroke-dasharray", ("3, 3")); | |
} | |
svg.append('line') | |
.attr('x1', p1980[0]) | |
.attr('y1', p1980[1]) | |
.attr('x2', p2009[0]) | |
.attr('y2', p2009[1]) | |
.style('stroke', 'black') | |
.style('stroke-width', 1.3); | |
svg.append('circle') | |
.attr('cx', p2009[0]) | |
.attr('cy', p2009[1]) | |
.attr('r', '3') | |
.attr('fill', 'red') | |
var plabel = get_xy(max * 1.04, i); | |
svg.append('text') | |
.attr('x', plabel[0]) | |
.attr('y', plabel[1]) | |
.attr('dy', function(){return get_dy(i)}) | |
.attr('text-anchor', get_anchor(i)) | |
.attr('class', 'label') | |
.text(item.location) | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.label { | |
font-family: sans-serif; | |
font-size: 8px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment