Built with blockbuilder.org
forked from tomshanley's block: Square matrix
forked from tomshanley's block: bar chart matrix
forked from tomshanley's block: bar chart matrix
forked from tomshanley's block: square matrix
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;top:0;right:0;bottom:0;left:0;font-family:Arial, sans-serif }
rect, line { shape-rendering: crispEdges; }
.box text { fill: white; }
.annotation rect, .annotation line { fill: none; stroke: #002e5e; stroke-dasharray: 2,2 }
.annotation text { fill: #002e5e; font-size: 14}
</style>
</head>
<body>
<script>
const data = [
{
"familyType": "Couple over 50",
"disadvantage": "Health",
"percentage": 0.15
},
{
"familyType": "Couple under 50",
"disadvantage": "Health",
"percentage": 0.04
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Health",
"percentage": 0.09
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Health",
"percentage": 0.04
},
{
"familyType": "Couple over 50",
"disadvantage": "Education",
"percentage": 0.17
},
{
"familyType": "Couple under 50",
"disadvantage": "Education",
"percentage": 0.13
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Education",
"percentage": 0.09
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Education",
"percentage": 0.18
},
{
"familyType": "Couple over 50",
"disadvantage": "Housing",
"percentage": 0.19
},
{
"familyType": "Couple under 50",
"disadvantage": "Housing",
"percentage": 0.11
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Housing",
"percentage": 0.13
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Housing",
"percentage": 0.12
},
{
"familyType": "Couple over 50",
"disadvantage": "Employment",
"percentage": 0.15
},
{
"familyType": "Couple under 50",
"disadvantage": "Employment",
"percentage": 0.11
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Employment",
"percentage": 0.07
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Employment",
"percentage": 0.17
},
{
"familyType": "Couple over 50",
"disadvantage": "Income",
"percentage": 0.17
},
{
"familyType": "Couple under 50",
"disadvantage": "Income",
"percentage": 0.19
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Income",
"percentage": 0.16
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Income",
"percentage": 0.09
},
{
"familyType": "Couple over 50",
"disadvantage": "Connectedness",
"percentage": 0.24
},
{
"familyType": "Couple under 50",
"disadvantage": "Connectedness",
"percentage": 0.18
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Connectedness",
"percentage": 0.24
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Connectedness",
"percentage": 0.21
},
{
"familyType": "Couple over 50",
"disadvantage": "Material disadvantage",
"percentage": 0.13
},
{
"familyType": "Couple under 50",
"disadvantage": "Material disadvantage",
"percentage": 0.14
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Material disadvantage",
"percentage": 0.11
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Material disadvantage",
"percentage": 0.11
},
{
"familyType": "Couple over 50",
"disadvantage": "Crime",
"percentage": 0.17
},
{
"familyType": "Couple under 50",
"disadvantage": "Crime",
"percentage": 0.18
},
{
"familyType": "Single parent, child under 18",
"disadvantage": "Crime",
"percentage": 0.05
},
{
"familyType": "Couples, child under 18",
"disadvantage": "Crime",
"percentage": 0.08
}
];
const width = 500;
const height = 600;
const margin = {"top": 150, "left": 200, "right": 150, "bottom": 50};
const annotationPadding = 1;
const rowPadding = 10;
const annotationPaddingV = rowPadding/2;
var sortOrderDisadvantage = ["Education",
"Employment",
"Crime",
"Income",
"Material disadvantage",
"Connectedness",
"Health",
"Housing"];
var nestByFamilyType = d3.nest()
.key(function(d){ return d.familyType; })
.sortKeys(d3.ascending)
.entries(data);
var columnWidth = width/nestByFamilyType.length;
var maxPercentage = d3.max(data, function(d){ return d.percentage; });
var scale = d3.scaleSqrt()
.domain([0,maxPercentage]);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom);
var chart = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var columnHeader = chart.append("g")
.attr("transform", "translate(0,0)");
columnHeader.append("text")
.text("Family type")
.attr("x", width/2)
.attr("y", -40)
.style("text-anchor", "middle")
/*columnHeader.append("text")
.text("Disadvantage")
.attr("x", -rowPadding)
.attr("y", 0)
.style("text-anchor", "end")*/
var columnLabels = columnHeader.selectAll("g")
.data(nestByFamilyType)
.enter()
.append("g")
.attr("transform", function(d, i) {return "translate(" + (columnWidth * i) +",0)"; });
columnLabels.append("text")
.text(function(d) { return d.key })
.attr("y", -10);
//.attr("transform", "translate(20)rotate(-45)")
var nestByDisadvantage = d3.nest()
.key(function(d){ return d.disadvantage; })
.sortKeys(d3.ascending)
.sortValues(function(a,b) { return a.familyType < b.familyType; })
.entries(data);
var rowHeight = height/nestByDisadvantage.length;
scale.range([0,(rowHeight - rowPadding)]);
nestByDisadvantage.forEach(function(d) {
var rowNumber = sortOrderDisadvantage.indexOf(d.key);
var rowG = chart.append("g")
.attr("transform", "translate(0," + (rowNumber * rowHeight) + ")");
var percentages = [];
d.values.forEach(function(d,i){
percentages[i] = d.percentage;
})
percentages.sort(function(a, b){return b-a}); //decsending
var colour = d3.scaleOrdinal()
.range(['#bf1c7d','#7EA5B5','#A2BFCB','#B4CCD6'])
.domain(percentages);
rowG.append("text")
.text(d.key)
.attr("x", -rowPadding)
.attr("y", rowHeight/2 + 6)
.style("text-anchor", "end");
var boxes = rowG.selectAll("g")
.data(d.values)
.enter()
.append("g")
.attr("class", "box")
.attr("transform", function(d, i) {return "translate(" + (columnWidth * i) +",0)"; });
//var barWidth = columnWidth * 0.9;
boxes.append("rect")
.attr("x", function(d) { return (columnWidth - scale(d.percentage))/2; })
.attr("y", function(d) { return (rowHeight - scale(d.percentage))/2; })
.attr("width", function(d) { return scale(d.percentage); })
.attr("height", function(d) { return scale(d.percentage); })
.style("fill", function(d){ return colour(d.percentage); });
boxes.append("text")
.text(function(d){ return formatPercentage(d.percentage) })
.attr("x", columnWidth/2)
.attr("y", rowHeight/2 + 6)
.style("text-anchor", "middle");
/*boxes.on("click", function(d){
var thisRect = d3.select(this)
.select("rect");
currentColour = thisRect.style("fill");
thisRect.transition()
.duration(250)
.attr("width", 0)
.attr("x", columnWidth/2)
.transition()
.duration(0)
.style("fill", function(d) { return currentColour == "rgb(0, 0, 0)" ? colour(d.percentage) : "black"; })
.transition()
.duration(250)
.attr("width", function(d) { return scale(d.percentage); })
.attr("x", function(d) { return (columnWidth - scale(d.percentage))/2; })
.style("fill", function(d) { return currentColour == "rgb(0, 0, 0)" ? colour(d.percentage) : "black"; });
});*/
});
//annotations col, row text
var annotations = [
/*{"col": 1, "row": 6, "w": 2, "h": 2, "text": "this is an annotation", "direction": "bottom"},*/
{"col": 3, "row": 3, "w": 2, "h": 3, "text": "this is an annotation", "direction": "left"},
{"col": 4, "row": 6, "w": 1, "h": 3, "text": "this is an annotation", "direction": "left"},
{"col": 2, "row": 1, "w": 1, "h": 2, "text": "this is an annotation", "direction": "left"}
];
var annotation = chart.selectAll(".annotation")
.data(annotations)
.enter()
.append("g")
.attr("class", "annotation")
.attr("transform", function(d) { return"translate(" + (width + 5) + "," + annotationY(d.row) + ")"; });
/*annotation.append("rect")
.attr("class", "annotation")
.attr("x", 0)
.attr("y", 0)
.attr("width", function(d) { return annotationWidth(d.w); })
.attr("height", function(d) { return annotationHeight(d.h); })
.attr("rx", 3);*/
annotation.append("line")
.attr("x1", 0)
.attr("y1", annotationPaddingV)
.attr("x2", 0)
.attr("y2", function(d) { return annotationHeight(d.h) - annotationPaddingV; });
annotation.append("line")
.attr("x1", 0)
.attr("y1", function(d) { return annotationHeight(d.h)/2; })
.attr("x2", rowPadding)
.attr("y2", function(d) { return annotationHeight(d.h)/2; });
annotation.append("line")
.attr("x1", 0)
.attr("y1", annotationPaddingV)
.attr("x2", -rowPadding)
.attr("y2", annotationPaddingV);
annotation.append("line")
.attr("x1", 0)
.attr("y1", function(d) { return annotationHeight(d.h) - annotationPaddingV; })
.attr("x2", -rowPadding)
.attr("y2", function(d) { return annotationHeight(d.h) - annotationPaddingV; });
/*annotation.append("line")
.attr("x1", function(d) { return d.direction == "left" ? annotationWidth(d.w) : annotationWidth(d.w)/2; })
.attr("y1", function(d) { return d.direction == "left" ? annotationHeight(d.h)/2 : annotationHeight(d.h); })
.attr("x2", function(d) { return annotationTextX(d.direction, d.w, d.col); })
.attr("y2", function(d) { return annotationTextY(d.direction, d.h, d.row); });*/
annotation.append("text")
.text(function(d){ return d.text })
.attr("x", 12)
.attr("y", function(d) { return annotationHeight(d.h)/2 + 4; });
function annotationX(d) {
return (columnWidth * annotationPosition(d)) + annotationPadding;
}
function annotationY(d) {
return rowHeight * annotationPosition(d) + annotationPadding;
}
function annotationWidth(d) {
return (columnWidth * d) - (2 * annotationPadding);
};
function annotationHeight(d) {
return (rowHeight * d) - (2 * annotationPadding);
};
function annotationPosition(d) {
return d - 1;
};
function annotationTextX(direction, w, col) {
if (direction == "left") {
return annotationWidth(5 - col) + 20;
} else {
return annotationWidth(w)/2;
};
};
function annotationTextY(direction, h, row) {
if (direction == "left") {
return annotationHeight(h)/2;
} else {
return annotationHeight(9 - row) + 20;
};
};
function formatPercentage(n) {
return Math.round(n * 100);
}
</script>
</body>
https://d3js.org/d3.v4.min.js