trafficLightMatrixGraph = (iwidth = 0.98 * window.innerWidth, iheight = iwidth/phi) => {
let boxSize = 20, Duration = 1000;
let margin = {top: 10, bottom: 10, left: 10, right: 10};
let svg = d3.create("svg").attr("width", iwidth).attr("height", iheight).style("background", "#FFF");
let container = svg.append("g").attr("class", "container").attr("transform", `translate(${[margin.left, margin.top]})`);
let width = iwidth - margin.left - margin.right;
let height = iheight - margin.top - margin.bottom;
function renderSquares(array) {
let scaleRows = d3.scaleBand()
.domain([...new Set(array.map(d => d.dashboard).sort((a,b) => d3.ascending(a.dashboard, b.dashboard)))])
.range([0, height])
.align(1)
.round(true);
let scaleColumns = d3.scaleBand()
.domain([...new Set(array.map(d => d.machine).sort((a,b) => d3.ascending(a.machine, b.machine)))])
.range([0, width])
.align(1)
.round(true);
let rects = container.selectAll("rect.box").data(d => array, d => `${d.dashboard}-${d.machine}`);
rects
.enter()
.append("rect")
.attr("class", "box")
.attr("height", (d,i) => scaleRows.bandwidth())
.attr("fill", (d,i) => d.color)
.attr("stroke", (d,i) => "#FFF")
.attr("stroke-width", phi/2)
.transition()
.duration(Duration)
.delay((d,i) => i * 10)
.attr("transform", (d,i) => `translate(${[scaleColumns(d.machine), scaleRows(d.dashboard)]})`)
.attr("width", (d,i) => scaleColumns.bandwidth())
rects
.transition()
.duration(Duration)
.attr("fill", (d,i) => d.color)
.attr("height", (d,i) => scaleRows.bandwidth())
.attr("transform", (d,i) => `translate(${[scaleColumns(d.machine), scaleRows(d.dashboard)]})`)
.attr("width", (d,i) => scaleColumns.bandwidth())
rects
.exit()
.transition()
.duration(Duration)
.attr("width", (d,i) => 0)
.remove();
}
return Object.assign(svg.node(), {
update(data) {
renderSquares(data);
}
})
}