Skip to content

Instantly share code, notes, and snippets.

@timproDev
Last active December 27, 2021 22:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timproDev/f87388942ca951c092a97c70f07fc979 to your computer and use it in GitHub Desktop.
Save timproDev/f87388942ca951c092a97c70f07fc979 to your computer and use it in GitHub Desktop.
Pareto Chart
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Timmy's Pareto Chart!</title>
<!-- css dynamically injected -->
</head>
<body>
<section style="width:80%; margin:5rem auto;">
<div class="mx-dv-container" id="paretoChart">
<div class="plot-wrap w-svg"></div>
<div class="plot-wrap no-svg">
<!-- <img src="assets/d3-bundles/horiz-barchart.png"> -->
</div>
<form class="chart-ui-container">
<div class="chart-form__radio">
<label id="dataChangeOne" class="chart-form__radio-label"><input class="chart-form__radio-input" type="radio" name="dataset" value="line">Line Order</label>
</div>
<div class="chart-form__radio">
<label id="dataChangeTwo" class="chart-form__radio-label"><input class="chart-form__radio-input" type="radio" name="dataset" value="bar">Bar Order</label>
</div>
<div class="chart-form__radio">
<label id="dataChangeTwo" class="chart-form__radio-label"><input class="chart-form__radio-input" type="radio" name="dataset" value="date">Date Order</label>
</div>
</form>
</div>
</section>
<script src="pareto-chart.js"></script>
<script src="pareto-chart-init.js"></script>
<script src="https://rawgit.com/timproDev/d3-first-timer/master/js/d3v4-473-jetpack.js"></script>
</body>
</html>
document.addEventListener("DOMContentLoaded", function(){
// set global variables
var path = '';
var dataFile = 'placeholder-dataset.csv';
var elemContainer = ['#paretoChart'];
var uiEl = '.chart-ui-container input';
var cssFile = 'pareto-chart.css';
var globalDataX = 'header_five_date';
var oneDataY = 'header_two_amount';
var twoDataY = 'header_three_amount';
// instantiate constructor methods
var paretoChart = new ParetoChart({
elem:document.querySelector(elemContainer[0]),
globalDataX:'header_five_date',
oneDataY:'header_two_amount',
twoDataY:'header_three_amount',
data: path + dataFile,
transSpeed:350
});
// fire chart and events
// chartInit(instance, element, dataPath)
chartInit(paretoChart, elemContainer, dataFile);
function chartInit(chartInst, elem, dataFile){
d3.csv((path + dataFile), function(data) {
// convert defined header values to number
var parseTime = d3.timeParse("%d/%m/%Y");
data.forEach(function(d) {
d[globalDataX] = parseTime(d[globalDataX]);
d[oneDataY] = +d[oneDataY];
d[twoDataY] = +d[twoDataY];
});
chartInst.setData(data);
var inputs = document.querySelectorAll(elem + ' ' + uiEl);
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('click', function(){
var value = this.value;
if (value === 'line') {
data.sort(function(a,b){
return d3.ascending(+a[twoDataY], +b[twoDataY])
});
} else if (value === 'bar') {
data.sort(function(a,b){
return d3.ascending(+a[oneDataY], +b[oneDataY])
});
} else if (value === 'date') {
data.sort(function(a,b){
return d3.ascending(+a[globalDataX], +b[globalDataX])
});
}
chartInst.setData(data);
});
}
});
}
// include resize event
d3.select(window).on('resize', function(){
paretoChart.resize();
});
// inject custom chart css
function styleLink(){
var linkElem = document.createElement('link');
document.getElementsByTagName('head')[0].appendChild(linkElem);
linkElem.rel = 'stylesheet';
linkElem.type = 'text/css';
linkElem.href = (path + cssFile);
}
styleLink();
});
* {
font-family: arial, verdana, sans-serif;
color:#808080;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
line {
shape-rendering: crispEdges;
/*stroke:#aeaeae;
stroke-width:1;*/
}
.tooltip {
box-shadow: 0 2px 4px 0px rgba(0, 0, 0, 0.5);
border-radius: 2px;
background-color: #fff;
top: -1000px;
position: fixed;
padding: .65rem;
pointer-events: none;
max-width: 25%;
z-index: 500;
}
.tooltip-info {
padding: 0;
margin: 0;
display: block;
width: 100%;
}
.tooltip-hidden {
opacity: 0;
transition: all .3s;
transition-delay: .1s;
}
.chart-ui-container {
display: block;
width: 100%
margin:0 auto;
padding: 0 0 0 0;
text-align: center;
}
.chart-ui-container .chart-form__radio {
display: inline-block;
padding: 0;
margin-right: 1rem;
}
.chart-ui-container .chart-form__radio-label {
display: inline-block;
padding: 0 .15rem;
font-size: .8rem;
}
.chart-ui-container .chart-form__radio-input {
margin-right: .5rem;
cursor: pointer;
outline:none;
}
var ParetoChart = function(opts){
this.globalDataX = this.globalDataX || opts.globalDataX;
this.oneDataY = this.oneDataY || opts.oneDataY;
this.twoDataY = this.twoDataY || opts.twoDataY;
this.element = opts.elem.querySelector('.plot-wrap.w-svg');
}
ParetoChart.prototype.setData = function(newData){
this.data = newData;
this.draw();
}
ParetoChart.prototype.draw = function(){
this.margin = {
top:40,
left:20,
right:20,
bottom:80
};
this.width = this.element.offsetWidth - this.margin.left - this.margin.right;
this.height = this.width / 3 - (this.margin.top - this.margin.bottom);
this.element.innerHTML = '';
var svg = d3.select(this.element).append('svg');
svg.attr('width', this.width + (this.margin.left + this.margin.right));
svg.attr('height', (this.height + this.margin.top + this.margin.bottom));
this.plot = svg.append('g')
.attr('transform',`translate(${this.margin.left},${this.margin.top})`);
this.createOneScales()
this.createTwoScales()
this.addGrey()
this.addOneAxis()
this.addTwoAxis()
this.addRect();
this.addLine()
this.addDots()
this.addOneLabels()
this.addTwoLabels()
this.cleanUp()
this.addMouseEvent()
}
ParetoChart.prototype.createOneScales = function() {
var self = this
this.xScaleGlobal = d3.scaleBand()
.rangeRound([0,this.width])
.domain(this.data.map(function(d) { return d[self.globalDataX]; }))
.paddingInner(0.15);
this.yScaleOne = d3.scaleLinear()
.domain([0, d3.max(this.data, function(d){ return d[self.oneDataY];})])
.range([this.height,0]);
}
ParetoChart.prototype.createTwoScales = function() {
var self = this
this.yScaleTwo = d3.scaleLinear()
.domain([0, d3.max(this.data, function(d){ return d[self.twoDataY];})])
.range([this.height,0]);
}
ParetoChart.prototype.addOneAxis = function(){
var self = this
this.xAxisOne = d3.axisBottom(this.xScaleGlobal)
.tickFormat(d3.timeFormat("%a %Y"));
this.yAxisOne = d3.axisLeft()
.scale(this.yScaleOne)
.ticks(8)
.tickFormat(d3.format(""))
.tickSize(-this.width);
this.plot.append("g.x-axis")
.call(this.xAxisOne)
.attr("transform","translate(0," + this.height + ")");
this.plot.append("g.y-axis-bar")
.call(this.yAxisOne);
}
ParetoChart.prototype.addTwoAxis = function(){
var self = this
this.yAxisTwo = d3.axisRight()
.scale(this.yScaleTwo)
.ticks(8)
.tickFormat(d3.format(""))
.tickSize(this.width);
this.plot.append("g.y-axis-line")
.call(this.yAxisTwo);
}
ParetoChart.prototype.addDots = function() {
var self = this
this.gDot = this.plot.selectAll('.g-comp-dot')
.data(this.data)
.enter()
.append('g.g-comp-dot')
.append("circle.comp-dot")
.attr('fill','brown')
.attr("r",3)
.attr("cx",function(d){
return self.xScaleGlobal(d[self.globalDataX])+(self.xScaleGlobal.bandwidth()/2);
})
.attr('cy', this.height)
.transition().delay(function(d, i) { return i * 15; })
.attr("cy",function(d){
return self.yScaleTwo(d[self.twoDataY]);
});
}
ParetoChart.prototype.addLine = function() {
var interpolateTypes = [
d3.curveLinear, // 1
d3.curveStepBefore, // 2
d3.curveStepAfter, // 3
d3.curveBasis, // 4
d3.curveBasisOpen, // 5
d3.curveBasisClosed, // 6
d3.curveBundle, // 7
d3.curveCardinal, // 8
d3.curveCardinal, // 9
d3.curveCardinalOpen, // 10
d3.curveCardinalClosed, // 11
d3.curveNatural // 12
];
var self = this
this.lineGen = d3.line()
.x( function(d){ return self.xScaleGlobal(d[self.globalDataX])+(self.xScaleGlobal.bandwidth()/2); })
.y( function(d){ return self.yScaleTwo(d[self.twoDataY]); })
.curve(interpolateTypes[0]);
this.gLine = this.plot
.append("path.line-path")
.attr("d", this.lineGen(this.data))
.attr('fill','none')
.attr('stroke','brown')
.attr('stroke-width',1);
}
ParetoChart.prototype.addRect = function() {
var self = this
this.gRects = this.plot.selectAll('.g-comp-rect')
.data(this.data)
.enter()
.append('g.g-comp-rect')
.append('rect.comp-rect')
.style('fill', this.lineColor || 'salmon')
.attr("x",function(d){
return self.xScaleGlobal(d[self.globalDataX]);
})
.attr('y', this.height)
.transition().delay(function(d, i) { return i * 15; })
.attr("y",function(d){
return self.yScaleOne(d[self.oneDataY]);
})
.attr('width',this.xScaleGlobal.bandwidth())
.attr('height', function(d){
return self.height - self.yScaleOne(d[self.oneDataY]);
});
}
ParetoChart.prototype.addOneLabels = function(){
var self = this
this.plot.selectAll('.g-comp-rect')
.append("text.bar-label")
.attr("x", function(d){
return self.xScaleGlobal(d[self.globalDataX])+(self.xScaleGlobal.bandwidth()/2);
})
.attr("y",function(d){
return self.yScaleOne(d[self.oneDataY]);
})
.attr("dy", "-10px")
.attr("text-anchor","middle")
.attr('fill','salmon')
.attr('font-size','10px')
.text(function(d) { return d[self.oneDataY]; });
}
ParetoChart.prototype.addTwoLabels = function(){
var self = this
this.plot.selectAll('.g-comp-rect')
.append("text.line-label")
.attr("x", function(d){
return self.xScaleGlobal(d[self.globalDataX])+(self.xScaleGlobal.bandwidth()/2);
})
.attr("y",function(d){
return self.yScaleTwo(d[self.twoDataY]);
})
.attr("dy", "-10px")
.attr("text-anchor","middle")
.attr('fill','brown')
.attr('font-size','10px')
.text(function(d) { return d[self.twoDataY]; });
}
ParetoChart.prototype.addMouseEvent = function () {
var self = this;
this.plot.selectAll('rect.comp-rect')
.on('mouseenter', function(d){
var thisData = d;
self.gLine.transition(50).style('opacity','.25');
d3.selectAll('rect.comp-rect, .g-comp-dot').transition(50).style('opacity',function (d,i) {
return (d === thisData) ? 1.0 : 0.25;
});
})
.on('mouseleave', function(d){
self.gLine.transition(50).style('opacity','1');
d3.selectAll('rect.comp-rect, .g-comp-dot').transition(50).style('opacity',function () {
return 1.0;
});
});
}
ParetoChart.prototype.addGrey = function(){
var self = this
this.plot.selectAll('.g-comp-rect')
.data(this.data)
.enter()
.append('rect.bg-bar')
.style('fill', this.lineColor || '#f3f3f3')
.attr("x",function(d){
return self.xScaleGlobal(d[self.globalDataX]);
})
.attr('y', 0)
.attr('width',this.xScaleGlobal.bandwidth())
.attr('height', this.height);
}
ParetoChart.prototype.cleanUp = function(){
var self = this
this.domain = this.plot.selectAll('.domain').style('display','none');
this.yBarTick = this.plot.selectAll('.y-axis-bar .tick line')
.attr('stroke','#e0e0e0')
.attr('stroke-width',1);
this.yLineTick = this.plot.selectAll('.y-axis-line .tick line').attr('display','none');
this.xText = this.plot.selectAll('.x-axis .tick text')
.attr('text-anchor','end')
.attr('y', function(d) { return self.xScaleGlobal.bandwidth() - (self.xScaleGlobal.bandwidth()+3); })
.attr('x',-10)
.attr("transform", "rotate(-90)");
}
ParetoChart.prototype.resize = function(){
console.log('sdc')
this.width = parseInt(d3.select(this.element).style('width'), 10);
this.draw();
}
header_one_name header_two_amount header_three_amount header_four_text_string header_five_date
Mahatma Gandhi 50 91 faucibus 30/04/2013
Anwar Sadat 64 444 viverra 20/11/2017
Nikola JuriçiÛˆ 13 68 non 23/08/2015
Sargon the Great 30 76 purus 15/11/2015
Toyotomi Hideyoshi 73 270 sed 27/01/2015
Ronald Reagan 95 495 amet 17/02/2015
Salah al-Din 97 367 tellus 27/11/2013
Alfred the Great 71 124 quisque 20/10/2016
CYRUS the GREAT 31 32 duis 15/02/2015
Niccolí_ Machiavelli 87 80 fusce 16/05/2013
Darius The Great 20 69 euismod 28/02/2015
Vladimir Lenin 30 247 massa 15/07/2013
Vladimir Putin 35 373 commodo 13/04/2013
Harry S. Truman 2 400 duis 19/04/2013
Vladimir Lenin 48 364 eu 15/03/2017
Augustus Caesar 22 245 egestas 21/04/2015
Ho Chi Minh 9 286 purus 24/03/2015
Josip Broz Tito 64 414 sed 17/08/2014
Alexander The Great 42 147 venenatis 24/09/2015
Queen Isabella of Spain 8 48 ut 17/04/2017
Nelson Mandela 93 290 leo 23/06/2017
Hannibal 98 490 enim 16/11/2015
Tupac Yupanqui 79 292 enim 29/09/2016
Empress Jingu 10 197 nisi 16/03/2016
Sun Tzu 27 375 viverra 16/05/2015
Thomas Jefferson 99 104 libero 21/10/2015
Benito Mussolini 1 402 adipiscing 19/09/2017
Julius Caesar 80 183 pharetra 13/11/2014
Emperor Meiji 44 2 semper 31/12/2014
Che Guevara 3 221 at 28/02/2016
atilla the hun 89 70 id 19/02/2014
Sultan II. Abdulhamid Khan 10 352 id 25/08/2015
Queen Victoria 77 357 laoreet 24/05/2013
Hammurabi 71 207 lobortis 17/07/2017
Benjamin Franklin 36 39 eu 4/3/2013
T. E. Lawrence of Arabia 58 261 commodo 5/7/2014
William the Conqueror 88 85 laoreet 6/11/2017
Fidel Castro 5 341 quam 12/4/2016
Margaret Thatcher 19 120 nibh 5/9/2016
William I. 16 387 volutpat 8/6/2015
Charles de Gaulle 99 320 viverra 11/9/2013
Ashoka the Great 23 207 quisque 3/10/2017
Flavius Odoacer 60 20 nisl 5/11/2015
Moses 26 1 lectus 5/2/2015
Winston Churchill 55 328 justo 5/7/2017
Theoderic the Great 47 416 volutpat 5/2/2018
James Monroe 27 318 quisque 7/9/2014
Frederick the Great 73 294 netus 7/10/2014
Franklin D. Roosevelt 7 44 quis 1/11/2016
John Adams 71 455 tristique 12/9/2014
@daluu
Copy link

daluu commented Dec 27, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment