【D3.js 学习总结】15、D3布局-堆栈图

    xiaoxiao2026-03-07  3

    d3.layout.stack()

    什么是堆栈图。

    例如,有如下情况:

    某公司,销售三种产品:个人电脑、智能手机、软件。

    2005年,三种产品的利润分别为3000、2000、1100万。

    2006年,三种产品的利润分别为1300、4000、1700万。

    计算可得,2005年总利润为6100万,2006年为7000万。

    如果要将2005年的总利润用柱形表示,那么应该画三个矩形,三个矩形堆叠在一起。这时候就有一个问题:每一个矩形的起始y坐标是多少?高应该是多少?

    堆栈图布局(Stack Layout)能够计算二维数组每一数据层的基线,以方便将各数据层叠加起来,最适合用来处理以上这种场景。

    1、数据

    var dataset = [ { name: "PC" , sales: [ { year:2005, profit: 3000 }, { year:2006, profit: 1300 }, { year:2007, profit: 3700 }, { year:2008, profit: 4900 }, { year:2009, profit: 700 } ] }, { name: "SmartPhone" , sales: [ { year:2005, profit: 2000 }, { year:2006, profit: 4000 }, { year:2007, profit: 1810 }, { year:2008, profit: 6540 }, { year:2009, profit: 2820 } ] }, { name: "Software" , sales: [ { year:2005, profit: 1100 }, { year:2006, profit: 1700 }, { year:2007, profit: 1680 }, { year:2008, profit: 4000 }, { year:2009, profit: 4900 } ] } ];

    2、数据转换

    var stack = d3.layout.stack() .values(function(d){ return d.sales; }) .x(function(d){ return d.year; }) .y(function(d){ return d.profit; }); var data = stack(dataset);

    values方法指定需要转换的数据集;

    x方法指定数据集中X轴的字段;

    y方法指定数据集中Y轴的字段;

    转换后的数据如下:

    如图,sales的每一项都多了两个值:y0和y。y0即该层起始坐标,y是高度。x坐标有就是year,这些坐标都是在左上角为起点计算的,这点要注意。

    3、绘制图形

    生成SVG容器

    var width = 700; var height = 500; var svg = d3.select('body') .append('svg') .attr('width', width) .attr('height', height);

    生成图表容器

    var padding = { top: 50, right: 100, bottom: 50, left: 50 }; var charts = svg.append('g') .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')');

    生成颜色比例尺

    var colors = d3.scale.category10();

    生成X轴和Y轴比例尺

    var maxProfit = d3.max(data[data.length - 1].sales, function(d) { return d.y0 + d.y; }); var xScale = d3.scale.ordinal().domain([2005, 2006, 2007, 2008, 2009]).rangeBands([0, width - padding.left - padding.right], 0.3); var yScale = d3.scale.linear().domain([0, maxProfit]).range([0, height - padding.top - padding.bottom]);

    为每种类型数据创建容器

    var stack = charts.selectAll('.stakc') .data(data) .enter() .append('g') .classed('stack', true) .attr('fill', function(d, i) { return colors(i); })

    为每种类型数据创建矩形图

    var rect = stack.selectAll('rect') .data(function(d) { return d.sales; }) .enter() .append('rect') .attr('x', function(d) { return xScale(d.year); }) .attr('y', function(d) { return height - padding.top - padding.bottom - yScale(d.y0 + d.y); }) .attr('width', xScale.rangeBand()) .attr('height', function(d) { return yScale(d.y); })

    生成坐标轴

    var xAxis = d3.svg.axis().scale(xScale); var yAxis = d3.svg.axis().scale(yScale.range([height - padding.top - padding.bottom, 0])).orient('left'); charts.append('g') .classed('x axis', true) .attr('transform', 'translate(0,' + (height - padding.top - padding.bottom) + ')') .call(xAxis) charts.append('g') .classed('y axis', true) .call(yAxis)

    生成数据类型图示

    stack.append('circle') .attr('cx', function(d) { return width - padding.left - padding.right * 0.9 }) .attr('cy', function(d, i) { return i * 50 }) .attr('r', 5) stack.append('text') .attr('x', function(d) { return width - padding.left - padding.right * 0.8 }) .attr('y', function(d, i) { return i * 50 }) .attr('dy', 5) .text(function(d) { return d.name; })

    查看在线演示

    最新回复(0)