D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
mdrobinson
Full window
Github gist
Radial Bar Demo - Customer Dim
Built with
blockbuilder.org
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Customer Dimensions - Dairy</title> <style> body { font: 12px sans-serif; } svg { margin: 0px auto; display: block; } path.arc { opacity: 0.9; transition: opacity 0.5s; } path.arc:hover { opacity: 0.7; } .axis line, .axis circle { stroke: #cccccc; stroke-width: 1px } .axis circle { fill: none; } .r.axis text { text-anchor: end } .tooltip { position: absolute; display: none; background: rgba(0, 0, 0, 0.6); border-radius: 3px; box-shadow: -3px 3px 15px #888; color: white; padding: 6px; } rect.High { fill: green; } rect.Medium { fill: blue; } rect.Low { fill: grey; } </style> <script src="https://d3js.org/d3.v4.min.js"></script> </head> <body> <center><h1>Dairy Customer Dimensions</h1></center> <script> const width = 960, height = 500, chartRadius = height / 2 - 40; let svg = d3.select('body').append('svg') .attr('width', width) .attr('height', height) .append('g') .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); let tooltip = d3.select('body').append('div') .attr('class', 'tooltip'); const PI = Math.PI, arcMinRadius = 10, arcPadding = 15, labelPadding = -5, numTicks = 10; d3.csv('custDim.csv', (error, data) => { let scale = d3.scaleLinear() .domain([0, d3.max(data, d => d.value) * 1.1]) .range([0, 2 * PI]); let ticks = scale.ticks(numTicks).slice(0, -1); let keys = data.map((d, i) => d.name); //number of arcs const numArcs = keys.length; const arcWidth = (chartRadius - arcMinRadius - numArcs * arcPadding) / numArcs; let arc = d3.arc() .innerRadius((d, i) => getInnerRadius(i)) .outerRadius((d, i) => getOuterRadius(i)) .startAngle(0) .endAngle((d, i) => scale(d)) let axialAxis = svg.append('g') .attr('class', 'a axis') .selectAll('g') .data(ticks) .enter().append('g') .attr('transform', d => 'rotate(' + (rad2deg(scale(d)) - 90) + ')'); axialAxis.append('line') .attr('x2', chartRadius); axialAxis.append('text') .attr('x', chartRadius + 10) .style('text-anchor', d => (scale(d) >= PI && scale(d) < 2 * PI ? 'end' : null)) .attr('transform', d => 'rotate(' + (90 - rad2deg(scale(d))) + ',' + (chartRadius + 10) + ',0)') .text(d => d); //data arcs let arcs = svg.append('g') .attr('class', 'data') .selectAll('path') .data(data) .enter().append('path') .attr('class', 'arc') .style('fill', getBarColor) let radialAxis = svg.append('g') .attr('class', 'r axis') .selectAll('g') .data(data) .enter().append('g'); radialAxis.append('circle') .attr('r', (d, i) => getOuterRadius(i) + arcPadding); renderLegend(); arcs.transition() .delay((d, i) => i * 200) .duration(1000) .attrTween('d', arcTween); radialAxis.append('text') .attr('x', labelPadding) .attr('y', (d, i) => -getOuterRadius(i) + arcPadding) .style("font-weight", "bold") .text(d => d.name); arcs.on('mousemove', showTooltip) arcs.on('mouseout', hideTooltip) function getBarColor(d){ //debugger; var category = d.category; var color = (category == "High") ? ("green") : ((category == "Medium") ? ("blue") : ("grey")); return color; } function arcTween(d, i) { let interpolate = d3.interpolate(0, d.value); return t => arc(interpolate(t), i); } function showTooltip(d) { tooltip.style('left', (d3.event.pageX + 10) + 'px') .style('top', (d3.event.pageY - 25) + 'px') .style('display', 'inline-block') .html("Dairy " + d.name + " Score: " + d.value); } function hideTooltip() { tooltip.style('display', 'none'); } function rad2deg(angle) { return angle * 180 / PI; } function getInnerRadius(index) { return arcMinRadius + (numArcs - (index + 1)) * (arcWidth + arcPadding); } function getOuterRadius(index) { return getInnerRadius(index) + arcWidth; } function renderLegend() { //var self = this; var svg = d3.select("svg"); var containerWidth = d3.select("svg").clientWidth; // config var legendHeight = 200, colorWidth = 15, x = 875, y = 130, data = [{ cssClass: "High", display: "High" // there is no "really good" maximum }, { cssClass: "Medium", display: "Medium" }, { cssClass: "Low", display: "Low" } ]; // https://jsbin.com/ubafur/3/edit?js,output svg.select("g.legend1").remove(); // cleanup on previous runs var legend = svg .append("g") .attr("class", "legend1"); legend.selectAll('rect') .data(data) .enter() .append("rect") .attr("x", x) .attr("y", function(d, i) { return y + i * (legendHeight / data.length); }) .attr("width", colorWidth) .attr("height", legendHeight / 3) .attr("class", function(d) { return d.cssClass; }) .attr("stroke", "black") .attr("stroke-width", "1px"); legend.selectAll('text') .data(data) .enter() .append("text") .attr("x", x + colorWidth + 6) .attr("y", function(d, i) { return y + i * (legendHeight / (data.length)) + 40}) //{ return y + i * (legendHeight / (data.length + 1)) + 3; } .attr("pointer-events", "none") .attr("font-size", 12) .attr("font-weight", "bold") .attr("font-family", "Helvetica") .text(function(d) { return d.display }); // TODO - prepend or append units of measure legend .append("text") .attr("x", x) .attr("y", y - 7) .attr("pointer-events", "none") .attr("font-size", 12) .attr("font-family", "Helvetica") .attr("font-weight", "bold") .text("Group"); }; }); </script> </body> </html>
https://d3js.org/d3.v4.min.js