Built with blockbuilder.org
Created
July 11, 2018 21:02
-
-
Save mdrobinson/eb50f28cd36f5c25b2170c787f3b3243 to your computer and use it in GitHub Desktop.
Radial Bar Demo - Customer Dim
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
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
name | value | category | |
---|---|---|---|
Price | 18 | Low | |
Health | 87 | High | |
Convenience | 62 | Medium | |
Quality | 95 | High | |
Inspiration | 70 | High |
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> | |
<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" | |
} | |
]; | |
// http://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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment