forked from curran's block: Tilted Labels
forked from apratt2003's block: [unlisted] Satellites by Countries Interactive
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<title>Top Internet Countries Visualization</title>
<style>
body {
margin: 0px;
}
.domain {
display: none;
}
.tick line {
stroke: #C0C0BB;
}
.tick text {
fill: #8E8883;
font-size: 8pt;
font-family: sans-serif;
}
.axis-label {
fill: #635F5D;
font-size: 20pt;
font-family: sans-serif;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
const xValue = d => d.Country;
const xLabel = 'Country';
const yValue = "Number";
const yLabel = 'Total Satellites';
const colorColumn = 'Purpose';
const layerColumn = "Purpose";
const margin = { left: 150, right: 70, top: 20, bottom: 200 };
const svg = d3.select('svg');
const width = svg.attr('width');
const height = svg.attr('height');
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const xAxisG = g.append('g')
.attr('transform', `translate(0, ${innerHeight})`);
const yAxisG = g.append('g');
xAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', innerWidth / 2)
.attr('y', 185)
.text(xLabel);
yAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', -innerHeight / 2 - 30)
.attr('y', -100)
.attr('transform', `rotate(-90)`)
.style('text-anchor', 'middle')
.text(yLabel);
const xScale = d3.scaleBand()
.paddingInner(0.3)
.paddingOuter(0.2);
const yScale = d3.scaleLinear();
const xAxis = d3.axisBottom()
.scale(xScale)
.tickSize(-innerHeight);
const yTicks = 10;
const yAxis = d3.axisLeft()
.scale(yScale)
.ticks(yTicks)
.tickPadding(15)
//.tickFormat(d3.format('.0s'))
.tickSize(-innerWidth);
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);
function render(data){
colorScale.domain(data.map(function (d){
return d[colorColumn];
}));
var nested = d3.nest()
.key(xValue)
.key(function (d) {return d[layerColumn];})
.rollup(function (d) { return d[0].Number; })
.object(data);
var purposes = Object.keys(d3.nest()
.key(function (d) {return d[layerColumn];})
.object(data));
//console.log(purposes);
var transformed = Object.keys(nested)
.map(function (country) {
var row = {};
purposes.forEach(function (purpose){
if(nested[country][purpose]){
row[purpose] = nested[country][purpose];
} else {
// Fill in zero for missing values.
row[purpose] = 0;
}
});
row.Country = country;
return row;
});
console.log(transformed);
var stack = d3.stack()
.keys(purposes)
.order(d3.stackOrderNone)
.offset(d3.stackOffsetNone);
var stacked = stack(transformed);
console.log(stacked);
xScale
.domain(data.map(xValue)).range([0, innerWidth]);
yScale
.domain([0, d3.max(stacked.map(function (d){
return d3.max(d, function (d){ return d[1];});
}))])
//.domain([0, d3.max(data, yValue)])
.range([innerHeight, 0])
.nice(yTicks);
var layers = g.selectAll('g').data(stacked)
.enter().append('g')
.attr('fill', function(d) {
//console.log(d.key)
return colorScale(d.key);
});
var pancakes = layers.selectAll('rect').data(function (d) { return d; })
.enter().append('rect')
.attr('width', d => xScale.bandwidth())
.attr('x', function (d) {
return xScale(xValue(d.data))
})//d => xScale(xValue(d)))
.attr('y', function (d) {
return yScale(d[1]);
})//d => yScale(yValue(d)))
.attr('height', function (d) {
return yScale(d[0]) - yScale(d[1]);
}) //d => innerHeight - yScale(yValue(d)));
xAxisG.call(xAxis);
xAxisG.selectAll('.tick line').remove();
xAxisG.selectAll('.tick text')
.attr('transform', 'rotate(-45)')
.attr('text-anchor', 'end')
.attr('alignment-baseline', 'middle')
.attr('x', -5)
.attr('y', 6)
.attr('dy', 0);
yAxisG.call(yAxis);
function print(data){
d3.select("body").append("pre")
.text(JSON.stringify(nested, null, 2));
}
print()
}
function type(d) {
d.Number = +d.Number;
return d;
}
d3.csv('satpurpose.csv', type, render);
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js