Skip to content

Instantly share code, notes, and snippets.

@DIRKMJK
Last active April 6, 2019 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DIRKMJK/84a9cad46e1600c147b13658731cde1b to your computer and use it in GitHub Desktop.
Save DIRKMJK/84a9cad46e1600c147b13658731cde1b to your computer and use it in GitHub Desktop.
Radial lollipop chart
height: 620
scrolling: no
license: mit

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.

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}]};
<!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>
.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