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

简介: # d3.layout.stack() ![](https://img.alicdn.com/tps/TB1FpzeKFXXXXbgXFXXXXXXXXXX-704-472.png) 什么是堆栈图。 例如,有如下情况: 某公司,销售三种产品:个人电脑、智能手机、软件。 2005年,三种产品的利润分别为3000、2000、1100万。 2006年,三种产品的利润分

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;
    })

查看在线演示

目录
相关文章
|
3月前
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
164 33
|
4月前
Next.js 实战 (二):搭建 Layouts 基础排版布局
本文介绍了作者在Next.js v15.x版本发布后,对一个旧项目的重构过程。文章详细说明了项目开发规范配置、UI组件库选择(最终选择了Ant-Design)、以及使用Ant Design的Layout组件实现中后台布局的方法。文末展示了布局的初步效果,并提供了GitHub仓库链接供读者参考学习。
144 1
Next.js 实战 (二):搭建 Layouts 基础排版布局
|
5月前
|
Web App开发 JavaScript 前端开发
如何学习JavaScript?
如何学习JavaScript?
115 5
|
5月前
|
JavaScript 前端开发 索引
JavaScript学习第二章--字符串
本文介绍了JavaScript中的字符串处理,包括普通字符串和模板字符串的使用方法及常见字符串操作方法如`charAt`、`concat`、`endsWith`等,适合前端学习者参考。作者是一位热爱前端技术的大一学生,专注于分享实用的编程技巧。
58 2
|
5月前
|
存储 JavaScript 前端开发
JavaScript学习第一章
本文档介绍了JavaScript的基础知识,包括其在网页中的作用、如何通过JavaScript动态设置HTML元素的CSS属性,以及JavaScript中的变量类型(`var`、`let`、`const`)和数据类型(基本数据类型与引用数据类型)。通过实例代码详细解释了JavaScript的核心概念,适合初学者入门学习。
84 1
|
6月前
|
JavaScript
js学习--商品列表商品详情
js学习--商品列表商品详情
71 2
|
6月前
|
JavaScript
js学习--九宫格抽奖
js学习--九宫格抽奖
48 2
|
6月前
|
JavaScript
js学习--开屏弹窗
js学习--开屏弹窗
77 1
|
6月前
|
JavaScript 前端开发 容器
js之弹性布局使用方法
js之弹性布局使用方法
74 0
|
6月前
|
JavaScript 前端开发 容器
js之dom学习
js之dom学习
119 0
下一篇
oss创建bucket