|
<!-- ref: https://d3js.org/d3.v5.min.js --> |
|
<!-- Input Expected: Group, Set, Value --> |
|
<div id="ChartHtml"> |
|
<div id="chart1" style="background-color: white;"> |
|
<svg id="chartSVG" style="width:800px; height:600px;background-color: white;"></svg> |
|
</div> |
|
<script> |
|
const svg = d3.select("#chartSVG") |
|
const width = +svg.style("width").replace(/px/,"") |
|
const height = +svg.style("height").replace(/px/,"") |
|
const margin = { left: 30, right: 10, top: 5, bottom: 30} |
|
|
|
// Access Data Here |
|
const data = alteryxData() |
|
const getGroup = d => d.Group |
|
const getSet = d => d.Set |
|
const getValue = d => d.Value |
|
|
|
const totalByGroup = data.reduce((c, d) => { c[getGroup(d)] = (c[getGroup(d)] || 0) + getValue(d); return c }, {}) |
|
const groups = Object.keys(totalByGroup).sort((a,b) => -Math.sign(totalByGroup[a] - totalByGroup[b])) |
|
const x = d3.scaleBand().domain(groups).range([margin.left, width - margin.right]).padding(0.1) |
|
const xAxis = g => g |
|
.attr("transform", `translate(0,${height - margin.bottom})`) |
|
.call(d3.axisBottom(x).tickSizeOuter(0)) |
|
.call(g => g.selectAll(".domain").remove()) |
|
|
|
const sets = data.map(getSet).filter((v, i, a) => a.indexOf(v) === i) |
|
const color = d3.scaleOrdinal().unknown("#ccc").domain(sets).range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), sets.length).reverse()) |
|
|
|
const totals = groups.map(g => totalByGroup[g]) |
|
const y = d3.scaleLinear().domain([0, d3.max(totals)]).range([height - margin.bottom, margin.top]) |
|
const yAxis = g => g |
|
.attr("transform", `translate(${margin.left},0)`) |
|
.call(d3.axisLeft(y).ticks(null, "s")) |
|
.call(g => g.selectAll(".domain").remove()) |
|
|
|
const shapedData = sets.map(k => groups.map(g => d3.sum(data.filter(d => getGroup(d) === g && getSet(d) === k).map(getValue)))) |
|
sets.forEach((s,i) => shapedData[i] = shapedData[i].map((c, j) => (i === 0 ? [0, c] : [shapedData[i-1][j][1], c + shapedData[i-1][j][1]]))) |
|
|
|
svg |
|
.append("g") |
|
.selectAll("g") |
|
.data(shapedData) |
|
.enter().append("g") |
|
.attr("fill", (d, i) => color(sets[i])) |
|
.selectAll("rect") |
|
.data(d => d) |
|
.enter().append("rect") |
|
.attr("x", (d, i) => x(groups[i])) |
|
.attr("y", (d) => y(d[1])) |
|
.attr("height", d => y(d[0]) - y(d[1])) |
|
.attr("width", x.bandwidth()) |
|
|
|
svg.append("g").call(xAxis) |
|
svg.append("g").call(yAxis) |
|
|
|
const legend = svg |
|
.append("g") |
|
.attr("transform", `translate(${width - margin.right},${margin.top})`) |
|
.attr("font-family", "sans-serif") .attr("font-size", 10) |
|
.attr("text-anchor", "end") |
|
.selectAll("g") |
|
.data(sets.slice().reverse()) |
|
.enter().append("g") |
|
.attr("transform", (d, i) => `translate(0,${i * 20})`) |
|
legend.append("rect").attr("x", -19).attr("width", 19).attr("height", 19).attr("fill", color) |
|
legend.append("text").attr("x", -24).attr("y", 9.5).attr("dy", "0.35em").text(d => d) |
|
</script> |
|
</div> |