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

d3.layout.stack()

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

什么是堆栈图。

例如,有如下情况:

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

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轴的字段;

转换后的数据如下:

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

如图,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;
    })

查看在线演示

上一篇:JavaMail:在Web应用下完整接收、解析复杂邮件


下一篇:公司.NET 3.5培训资料分享