layout.stack()
const width = 800, height = 500, padding = {top: 160, left: 130};
const dataSet = [
{
name: "PC",
sales: [
{year: 2005, profit: 3000},
{year: 2001, profit: 2000},
{year: 2002, profit: 1000},
{year: 2003, profit: 5000},
{year: 2006, profit: 4000}
]
}, {
name: "Phone",
sales: [
{year: 2005, profit: 1000},
{year: 2001, profit: 2000},
{year: 2002, profit: 3000},
{year: 2003, profit: 3000},
{year: 2006, profit: 1000}
]
}, {
name: "SoftWare",
sales: [
{year: 2005, profit: 1600},
{year: 2001, profit: 2600},
{year: 2002, profit: 3600},
{year: 2003, profit: 6600},
{year: 2006, profit: 1600}
]
}
];
const stack = d3.layout.stack()
.values(d => d.sales)
.x(d => d.year)
.y(d => d.profit);
const data = stack(dataSet);
const svg = d3.select("body").append("svg")
.attr("width", width + padding.left * 2)
.attr("height", height + padding.top * 2)
.append("g");
const xScale = d3.scale.ordinal()
.domain(data[0].sales.map(d => d.year))
.rangeBands([0, width], .3);
const maxProfit = d3.max(data[data.length - 1].sales, d => d.y0 + d.y);
const yRangeWidth = height - padding.top;
const yScale = d3.scale.linear()
.domain([0, maxProfit])
.range([0, yRangeWidth]);
const color = d3.scale.category20b();
const groups = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.style("fill", (d, i) => color(i));
groups.selectAll("rect")
.data(d => d.sales)
.enter()
.append("rect")
.attr("x", d => xScale(d.year))
.attr("y", d => yRangeWidth - yScale(d.y0 + d.y))
.attr("width", xScale.rangeBand())
.attr("height", d => yScale(d.y))
.attr("transform", `translate(${padding.left},${padding.top})`);
const xAxis = d3.svg.axis().scale(xScale).orient("bottom");
svg.append("g").attr("class", "axis").attr("transform", `translate(${padding.left},${height})`).call(xAxis)
const yAxis = d3.svg.axis().scale(yScale).orient("left");
yScale.range([yRangeWidth, 0]);
svg.append("g").attr("class", "axis").attr("transform", `translate(${padding.left},${padding.top})`).call(yAxis)
const labHeight = 50;
const labRadius = 10;
const labelCircle = groups.append("circle")
.attr("cx", d => (width + padding.left * .9))
.attr("cy", (d,i) => (padding.top + labHeight*i))
.style("fill", (d, i) => color(i))
.attr("r", labRadius);
const labelText = groups.append("text")
.attr("x", d => width + padding.left )
.attr("y", (d,i) => (padding.top + labHeight*i))
.attr("dy", labRadius / 2)
.text(d => d.name);
结果:
曲线堆叠图
const width = 800, height = 500, padding = {top: 160, left: 130};
const dataSet = [
{
name: "PC",
sales: [
{year: 2005, profit: 3000},
{year: 2001, profit: 2000},
{year: 2002, profit: 1000},
{year: 2003, profit: 5000},
{year: 2006, profit: 4000}
]
}, {
name: "Phone",
sales: [
{year: 2005, profit: 1000},
{year: 2001, profit: 2000},
{year: 2002, profit: 3000},
{year: 2003, profit: 3000},
{year: 2006, profit: 1000}
]
}, {
name: "SoftWare",
sales: [
{year: 2005, profit: 1600},
{year: 2001, profit: 2600},
{year: 2002, profit: 3600},
{year: 2003, profit: 6600},
{year: 2006, profit: 1600}
]
}
];
const stack = d3.layout.stack()
.values(d => d.sales)
.x(d => d.year)
.y(d => d.profit);
const data = stack(dataSet);
const svg = d3.select("body").append("svg")
.attr("width", width + padding.left * 2)
.attr("height", height + padding.top * 2)
.append("g");
const xScale = d3.scale.ordinal()
.domain(data[0].sales.map(d => d.year))
.rangeBands([0, width], .3);
const maxProfit = d3.max(data[data.length - 1].sales, d => d.y0 + d.y);
const yRangeWidth = height - padding.top;
const yScale = d3.scale.linear()
.domain([0, maxProfit])
.range([0, yRangeWidth]);
const color = d3.scale.category20b();
const groups = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.style("fill", (d, i) => color(i));
const areaPath = d3.svg.area()
.x(d => xScale(d.year) + xScale.rangeBand() / 2)
.y0(d => yRangeWidth - yScale(d.y0))
.y1(d => yRangeWidth - yScale(d.y0 + d.y))
.interpolate("basis");
groups.selectAll(".area").data(data).enter().append("path")
.attr("class", "area")
.attr("d", function (d) {
return areaPath(d.sales);
})
.style("fill", (d, i) => color(i))
.attr("transform", `translate(${padding.left},${padding.top})`);
const xAxis = d3.svg.axis().scale(xScale).orient("bottom");
svg.append("g").attr("class", "axis").attr("transform", `translate(${padding.left},${height})`).call(xAxis)
const yAxis = d3.svg.axis().scale(yScale).orient("left");
yScale.range([yRangeWidth, 0]);
svg.append("g").attr("class", "axis").attr("transform", `translate(${padding.left},${padding.top})`).call(yAxis)
const labHeight = 50;
const labRadius = 10;
const labelCircle = groups.append("circle")
.attr("cx", d => (width + padding.left * .9))
.attr("cy", (d, i) => (padding.top + labHeight * i))
.style("fill", (d, i) => color(i))
.attr("r", labRadius);
const labelText = groups.append("text")
.attr("x", d => width + padding.left)
.attr("y", (d, i) => (padding.top + labHeight * i))
.attr("dy", labRadius / 2)
.text(d => d.name);
结果: