Skip to content

Instantly share code, notes, and snippets.

@Thanaporn-sk
Created November 1, 2019 14:31
Show Gist options
  • Save Thanaporn-sk/823ac70a833cbbe6f0f4e9fd6729eb72 to your computer and use it in GitHub Desktop.
Save Thanaporn-sk/823ac70a833cbbe6f0f4e9fd6729eb72 to your computer and use it in GitHub Desktop.
Radial Bar Demo - Customer Dim
license: mit
height: 800
border: no
scrolling: yes
name value category
Price 18 Low
Health 87 High
Convenience 62 Medium
Quality 95 High
Inspiration 70 High
<!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;
}
body span {
font-size: 18px;
font-weight:bold;
}
.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>
<span>Dairy Customer Dimensions</span>
<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