拖更了好久,最近毕业的手续办的差不多了,应该可以回来了...

系列传送门:

  1. D3可视化:(1)初次见面,SVG与D3的魅力
  2. D3可视化:(2)Bar Chart with D3js
  3. 更新中...

知识点:

  • d3数据绑定
  • 柱状图画法
  • 坐标轴
  • 比例尺

数据读入

数据可视化的第一步还是数据读取,在d3中可以使用d3.csv非常方便的读取数据,它会返回一个Promise对象。

csv文件是以逗号,分隔的数据内容,本地使用的csv数据如下,文件名为data.csv

country,population
China,1415046
India,1354052
United States,326767
Indonesia,266795
Brazil,210868
Pakistan,200814
Nigeria,195875
Bangladesh,166368
Russia,143965
Mexico,130759
复制代码

首先将数据读入,代码如下:

const data = d3.csv('data.csv').then(data => {console.log(data))
})
复制代码

可以看到,控制台输出了一个数组,数组中的每条数据均是一个对象,类型为{country:xx, population:xx}

当然,人数自然应该是Number类型的,同时,为了将人数转换为单位,将所有数据都扩大一千倍,即:

const data = d3.csv('data.csv').then(data => {data.forEach(element => {element.population = +element.population * 1000});  //处理完数据,就可以开始画图了render(data)
})
复制代码

画柱状图

HTML文件与上一节相同,都是仅包含了一个<svg></svg>标签,首先选择svg:

const svg = d3.select('svg');
const height = +svg.attr('height');
const width = +svg.attr('width');const render = data => {} //根据已有数据,画图渲染的函数
复制代码

数据绑定

将数据绑定到DOM上,是D3最大的特色。d3.selectd3.selectAll返回选择集,但其本身是没有数据的,通过data()函数,可以将数据与之绑定。相关函数有两个:

  • selection.datum([value]) 选择集上的每个元素都绑定相同的元素value
  • selection.data(values[,key]) 选择集上每一个元素分别绑定数组values的每一项,key是一个键函数,用于指定绑定数组时的规则。

datum用比较少,这里主要用到的是data(),将已处理好的数据绑定在dom上。

update、enter和exit

在进行数据绑定的时候,不一定数据和元素个数就是相同的,这个时候就需要一个动态的处理,这就需要用到updataenter、和exit了。

  • update() 当对应的元素正好满足时 ( 绑定数据数量 = 对应元素 ) 实际上并不存在这样一个函数,只是为了要与之后的 enter 和 exit 一起说明才想象有这样一个函数。但对应元素正好满足时,直接操作即可,后面直接跟 text ,style 等操作即可。
  • enter() 当对应的元素不足时 ( 绑定数据数量 > 对应元素 ) 当对应的元素不足时,通常要添加元素,使之与绑定数据的数量相等。后面通常先跟 append 操作。
  • exit() 当对应的元素过多时 ( 绑定数据数量 < 对应元素 ) 当对应的元素过多时,通常要删除元素,使之与绑定数据的数量相等。后面通常要跟 remove 操作。

本项目主要用到了enter,因为页面中只有svg标签,我们需要做的是根据数据内容,在svg中画<rect>来表示柱状图。 理解 Update、Enter、Exit

render函数

有了以上的概念,就可以开始画图了

const render = data => {svg.selectAll('rect').data(data)  //选择`rect`并绑定数据data,但这个时候没有元素,因此使用enter.enter().append('rect').attr('width',width).attr('height','30px')
}
复制代码

这样更新视图,就可以看到已经有图像出来了。但是只能看到一个黑色的长方形。因为目前图形并不能反映任何数据,只是单纯的固定'width'的长方形。为此,需要用上数据,但是因为数据可能很大或者很小,为了让其能够正好显示的视图中,需要使用到比例尺。

比例尺

D3中有很多比例尺,本例中主要使用到了线性比例尺(scaleLinear)和序数比例尺(scaleBand)

线性比例尺可以将domain的内容线性映射到range的一个范围内,这样,就可以保证无论初始数值多大或多小,都能够很好的适应画当前视图。 映射关系

序数比例尺不是一个连续的比例尺,domain()中使用一个数组,range()是一个连续域。 映射关系

因此,加上两个方向的比例尺,让柱状图的雏形开始慢慢出现吧:

const render = data => {const xScale = d3.scaleLinear().domain([0,d3.max(data, d => d.population)]).range([0,width]) //最大值将视图空间充满const yScale = d3.scaleBand().domain(data.map(d => d.country)).range([0,height])svg.selectAll('rect').data(data)  //选择`rect`并绑定数据data,但这个时候没有元素,因此使用enter.enter().append('rect').attr('y',d => yScale(d.country)).attr('width',d => xScale(d.population)) //宽度根据数据.attr('height',yScale.bandwidth()) //高度由比例尺自动生成
}
复制代码

这样子,就有一个雏形了,效果如下:

代码优化

首先,重新审视下代码,发现其中d => d.population以及d => d.country在比例尺设置以及使用时出现了多次,如果需要修改,又是代码中多处的重复修改。为此,对其进行一个处理,如下:

const render = data => {const xValue = d => d.population; //优化const yValue = d => d.country;  //优化const xScale = d3.scaleLinear().domain([0,d3.max(data,xValue)]) //优化.range([0,width]) const yScale = d3.scaleBand().domain(data.map(yValue))  //优化.range([0,height])svg.selectAll('rect').data(data) .enter().append('rect').attr('y',d => yScale(yValue(d)))   //优化.attr('width',d => xScale(xValue(d))) //优化.attr('height',yScale.bandwidth())
复制代码

坐标轴

使用margin来优化布局

下图所示是margin的布局示意图,因为直接按照svgheightwidth撑满画布将导致没有多余的位置放置坐标轴等,所以这里使用一个margin来对布局重新规划。

代码如下:

const margin = {left:50,top:10,right:20,bottom:30};
const innerHeight = height - margin.top - margin.bottom;
const innerWidth = width - margin.left - margin.right;
复制代码

其中innerHeight和innerWidth是柱状图的实际占有高度,因此,柱状图的代码可以修改为:

    const xScale = d3.scaleLinear().domain([0, d3.max(data,xValue)]).range([0, innerWidth]) //将 width 改为 innerWidthconst yScale = d3.scaleBand().domain(data.map(yValue)).range([0, innerHeight]) //将height 改为 innerHeightconst g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`) //加入新元素g,整体移动maring.left和margin.topg.selectAll('rect').data(data)  .enter().append('rect').attr('y',d => yScale(yValue(d))).attr('width', d => xScale(xValue(d))).attr('height',yScale.bandwidth())
复制代码

增加坐标轴

坐标轴的绘制,是d3通过<svg>中的<path> <text> <line>实现的,用到的函数如axisLeft axisBottom等,绘制一般分为一下几个步骤:

  • 创建坐标轴 var axisX = d3.axisLeft(xScale)根据比例尺创建坐标轴
  • 创建新的<g>var gAxis = svg.append('g')
  • 插入坐标轴 axisX(gAxis) 或者 在上一步直接svg.append('g').call(axisX)

因此,本例中坐标轴添加可以这样:

    g.append('g').call(d3.axisLeft(yScale)); //左边显示countryg.append('g').call(d3.axisBottom(xScale)).attr('transform',`translate(0,${innerHeight})`) //虽然是bottom,但是默认位置并不在下,需要移动至下方
复制代码

增加间隙

现在柱状图还是很丑的状态,应该增加一点间隙,让它看起来更加美观,这就非常简单了,在yScale上使用padding属性。

    const yScale = d3.scaleBand().domain(data.map(yValue)).range([0, innerHeight]).padding(0.15)   //增加了这个属性
复制代码

修改样式

为了让柱状图看起来更美观,增加一些css样式,样式如下:

body html{margin:0;overflow: hidden;}rect {fill:steelblue;}text {font-size: 1.1em;}
复制代码

最终效果

注意

由于chrome的安全原因限制,在本地使用d3.csv读取本地文件时是会遇到问题的,并不支持file//: 读取内容。 因此,代码在github中是可以正常运转,但是本地可能无法正常运作, 可以开一个本地服务器,将代码放置上。

完整代码

完整代码详见:d3系列教程源码

转载于:https://juejin.im/post/5c931cfa5188252d77391f3d

D3可视化:(2)Bar Chart with D3js相关推荐

  1. Python使用matplotlib可视化条形图(bar plot)、自定义在条形图的顶部添加数值标签(Bar Chart)

    Python使用matplotlib可视化条形图(bar plot).自定义在条形图的顶部添加数值标签(Bar Chart) 目录

  2. 数据可视化【四】Bar Chart

    Make a Bar Chart Representing a data table in JavaScript Creating rectangles for each row Using line ...

  3. Echarts+D3可视化开发工具集

    Echarts+D3可视化开发工具集 一.前言 ​ 大学三年期间,学的很杂,但唯一坚持的就是在做可视化开发,有个负责任的指导老师很重要.因为即将大四,之后不一定会再继续朝这个方面学习,所以把之前参加比 ...

  4. wps图表中如何插入甘特图_如何通过使用D3可视化数据集来构建类似甘特图的图表...

    wps图表中如何插入甘特图 by Déborah Mesquita 由DéborahMesquita 如何通过使用D3可视化数据集来构建类似甘特图的图表 (How to build a Gantt-l ...

  5. R语言ggplot2可视化:使用dplyr包计算每个分组个数的比例(对计算获得的百分比进行近似,值保留整数部分)、使用ggplot2可视化条形图(bar plot)、并在条形图上添加百分比标签

    R语言ggplot2可视化:使用dplyr包计算每个分组个数的比例(对计算获得的百分比进行近似,值保留整数部分).使用ggplot2可视化条形图(bar plot).并在条形图上添加百分比标签 目录

  6. R语言ggplot2可视化条形图(bar plot)、并为条形图添加误差条(error bar)、自定义设置误差条(error bar)的颜色/色彩( Barplots with Error bar)

    R语言ggplot2可视化条形图(bar plot).并为条形图添加误差条(error bar).自定义设置误差条(error bar)的颜色/色彩(Make Barplots with Error ...

  7. R绘制排序的条形图(Ordered Bar Chart)

    R绘制排序的条形图(Ordered Bar Chart) # 有序条形图 # 有序条形图是按Y轴变量排序的条形图.仅仅根据感兴趣的变量对数据表进行排序是不足以对条形图进行排序的.为了使条形图保持行的顺 ...

  8. 用Tableau画延展条形图(Extended Bar Chart)

    Extended Bar Chart来自Rajeev Pandey大神,他在前人的基础上进行了一些创造性的改进,把延展条形图带到了Tableau中.大家可以参考下面原文的介绍,学习基本的制图思路. h ...

  9. 16、17、18_使用gridspec定义多子图,条形图(Bar plots),分组条形图,堆叠条形图(Stacked bar chart),饼图(Pie plots),甜甜圈图,嵌套饼图

    16.使用gridspec定义多子图 16.1.图标题 17.条形图(Bar plots) 17.1.分组条形图 17.2.堆叠条形图(Stacked bar chart) 18.饼图(Pie plo ...

最新文章

  1. C语言memset函数详解(Linux下和windows下的差异)
  2. 决定局域网的主要技术要素
  3. Directx 顶点和顶点缓存
  4. 把URL参数解析成一个Json对象
  5. 一起谈.NET技术,.NET异步编程:IO完成端口与BeginRead
  6. 机器学习——常用核函数
  7. 【死磕 Spring】----- IOC 之解析 bean 标签:解析自定义标签
  8. Android之 ListView滑动时不加载图片
  9. JS操作地址栏Location
  10. kibana 查询_干货 | Elasticsearch、Kibana数据导出实战
  11. studio创建java工程_Android studio从头一步步创建Java项目
  12. 简易实践的vue自定义tab入门
  13. 微信小程序云开发教程-JavaScript入门(4)-捕捉异常
  14. vue echart甘特图
  15. MSSQL 2000 错误823恢复
  16. java门基础学习(五)
  17. 蓝牙耳机无法与计算机连接,蓝牙耳机怎么连接电脑【图文教程】
  18. 绿色数据中心基础设施建维服务认证
  19. MySQL 报错1055
  20. java pdf文件转换图片,pdf文件转图片(java实现)

热门文章

  1. 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用36
  2. zImage内核镜像解压过程详解
  3. 《OpenGL编程指南(原书第9版)》——1.4 OpenGL渲染管线
  4. 遇到的retain cycle例子
  5. UIWebView控件的简易浏览器小案例
  6. 谷歌:全球10大爬升最快搜索关键字排行榜 Google Zeitgeist 2011
  7. 深度解析:微软云计算平台的通信技术与应用开发
  8. 作业计算机组成与原理,课程计算机组成原理与汇编语言作业四
  9. java match parent_java.lang.IllegalStateException: The specified child already has a parent
  10. 结合使用 Hadoop 和 Couchbase