D3.js实现柱状图的方法详解


Posted in Javascript onSeptember 21, 2016

D3.js介绍

D3.js 是一个基于数据操作文档JavaScript库。D3帮助你给数据带来活力通过使用HTML、SVG和CSS。D3重视Web标准为你提供现代浏览器的全部功能,而不是给你一个专有的框架。结合强大的可视化组件和数据驱动方式Dom操作。这里也可以看到它是用SVG来呈现图表的,所以使用D3.js是需要一定的SVG基础的。

如何用D3.js实现柱状图?

柱状图里面有坐标轴和柱子。然而我们还需要SVG画布来画这些东西。先把大概的画图框架搭起来,代码如下(请注意此时我在body标签里添加了D3.js的script标签。这样我们后面才能使用D3的方法):

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>柱状图</title>
  <style>
   .container {
    margin: 30px auto;
    width: 600px;
    height: 300px;
    border: 1px solid #000;
   }
  </style>
 </head>
 <body>
  <div class="container">
   <svg width="100%" height="100%"></svg>
  </div>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script>
  <script>
   window.onload = function() {
    var width = 600, height = 300;
    // SVG画布边缘与图表内容的距离
    var padding = { top: 50, right: 50, bottom: 50, left: 50 };
    // 创建一个分组用来组合要画的图表元素
    var main = d3.select('.container svg').append('g')
     // 给这个分组加上main类
     .classed('main')
     // 设置该分组的transform属性
     .attr('transform', "translate(" + padding.top + ',' + padding.left + ')');
   };
  </script>
 </body>
</html>

坐标轴的实现

为了把真实的数据与SVG画布上的坐标轴上的坐标联系起来,我们需要定义比例尺来描述这样的对应关系。D3中常用的比例尺有线性比例尺和序数比例尺,它们的区别如图所示:

D3.js实现柱状图的方法详解

从图上可以看出,线性比例尺的对应关系是连续的,而序数比例尺的对应关系是离散的。分析柱状图的展现意义可以得出x轴应该选用序数比例尺,而y轴选用线性比例尺。

// 模拟数据
var dataset = {
 x: ["赵","钱","孙","李","周","吴","郑","王"],
 y: [40, 30, 50, 70, 90, 20, 10, 40]
};
// 定义x轴的比例尺(序数比例尺)
var xScale = d3.scale.ordinal()
  .domain(dataset.x)
  .rangeRoundBands([0, width - padding.left - padding.right],0,0);
// 定义y轴的比例尺(线性比例尺)
var yScale = d3.scale.linear()
  .domain([0, d3.max(dataset.y)])
  .range([height - padding.top - padding.bottom, 0]);
// 定义x轴和y轴
var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient('bottom');
var yAxis = d3.svg.axis()
  .scale(yScale)
  .orient('left');
// 添加坐标轴元素
main.append('g')
  .attr('class', 'axis')
  .attr('transform', 'translate(0,' + (height - padding.bottom - padding.top) + ')')
  .call(xAxis);
main.append('g')
  .attr('class', 'axis')
  .call(yAxis);

我们模拟了一些数据,每个姓氏对应了一个数值(从这里也可以看出序数比例尺的定义域上的值不一定是连续关系)。d3.scale.ordinal()创建了一个序数比例尺,而ordinal.domain()设置了该比例尺的定义域,ordinal.rangRoundBands()设置了值域。同理,d3.scale.linear()创建了一个线性比例尺,linear.domain()定义定义域,linear.range()定义值域。接着,我们用d3.svg.axis()创建了两个坐标轴,把比例尺应用到它们上面,并且用axis.orient()设置了坐标轴的刻度尺的方向。最后,添加SVG元素,用call()把定义好的坐标轴与SVG元素联系起来。通过设置它们的transform属性来移动元素,使它们看起来像是一个坐标系。

这里需要注意以下几点:

     1、ordinal.domain的参数是一个表示一系列值的数组,而linear.domain的参数是一个表示范围的数组。

     2、比例尺的本质是一个函数,它接收定义域上的值来得出对应的值域上的值。

应用序数比例尺的坐标轴与线性比例尺的有很大不同,这里大概说明一下。

D3.js实现柱状图的方法详解

  rangeRoundBands(interval, padding, outerPadding)中的padding和outerPadding都是可选的,默认为0。如上图所示的比例尺的代码是这样的。

var o = d3.scale.ordinal()
 .domain([0, 1, 2])
 .rangeRoundBands([0, 100], 0.4, 0.1);

  domain的参数数组有多少个元素,就会有多少个rangeBand,rangeBand之间的间隔为padding*step(padding取值范围为0到1),它与rangeBand的关系是均分一个step,比如padding为0.4,则rangeBand的长度为0.6*step。根据上述代码可得最终坐标轴的长度等于(0.1 + 2 + 0.6 + 0.1) * step,由此算出step的长度,再推出外间距、rangeBand、内间距的长度。而定义域上的取值刻度定位在每个rangeBand的中间。于是得到了示意图中的坐标轴(红色标注)。

我们接着来画柱状图,给坐标轴设置一下样式:

.axis path,
.axis line {
 stroke: #000;
 fill: none;
}

最终得到的柱状图的坐标轴如下图所示:

D3.js实现柱状图的方法详解

柱子的实现

柱子无非就是一个个矩形,在SVG中可以使用rect元素来画。先选择到main下所有bar类的元素(此时选择到的是一个空的集合),把dataset.y绑定到这个集合上,用enter()对比绑定的数组元素个数与集合中的SVG元素个数,与append()搭配使用,会自动补齐至两边个数相等。每一次的append都对应dataset.y中的一个数组元素。利用前面创建的比例尺函数计算出值并赋给举行元素的x、y属性。具体的代码如下:

// 矩形之间的间距
var rectMargin = 10;
// 添加矩形
main.selectAll('.bar')
  .data(dataset.y)
  .enter()
  .append('rect')
  .attr('class', 'bar')
  .attr('x', function(d, i) {
   return xScale(dataset.x[i]) + rectMargin;
  })
  .attr('y', function(d, i) {
   return yScale(d);
  })
  .attr('width', xScale.rangeBand() - 2*rectMargin)
  .attr('height', function(d, i) {
   return height - padding.top - padding.bottom - yScale(d);
  })
  .attr('fill', function(d, i) {
   return getColor(i);
  });

至此,得到了如下图所示的柱状图。

D3.js实现柱状图的方法详解

总结

以上就是利用D3.js实现柱状图的全部内容,感兴趣的朋友们可以自己动手实践下,这样更利于大家的理解和学习,希望这篇文章对大家的学习和工作能有所帮助。如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持,小编还会陆续更新关于D3.js的文章,请继续关注三水点靠木。

Javascript 相关文章推荐
jquery 查找select ,并触发事件的实现代码
Mar 30 Javascript
JQuery之focus函数使用介绍
Aug 20 Javascript
jquery()函数的三种语法介绍
Oct 09 Javascript
javascript折半查找详解
Jan 26 Javascript
jQuery选择器总结之常用元素查找方法
Aug 04 Javascript
微信小程序登录态控制深入分析
Apr 12 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
Apr 13 jQuery
JavaScript的继承实现小结
May 07 Javascript
使用travis-ci如何持续部署node.js应用详解
Jul 30 Javascript
Django+Vue实现WebSocket连接的示例代码
May 28 Javascript
js回文数的4种判断方法示例
Jun 04 Javascript
如何基于原生javaScript生成带图片的二维码
Nov 21 Javascript
AngularJS ng-style中使用filter
Sep 21 #Javascript
BootStrap与validator 使用笔记(JAVA SpringMVC实现)
Sep 21 #Javascript
JS实现简单的tab切换选项卡效果
Sep 21 #Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
Sep 21 #Javascript
JS 获取HTML标签内的子节点的方法
Sep 21 #Javascript
浅谈JS使用[ ]来访问对象属性
Sep 21 #Javascript
js style.display=block显示布局错乱问题的解决方法
Sep 21 #Javascript
You might like
第五节 克隆 [5]
2006/10/09 PHP
写一个用户在线显示的程序
2006/10/09 PHP
一个轻量级的javascript库 pj介绍
2010/12/19 Javascript
用JavaScript获取DOM元素位置和尺寸大小的方法
2013/04/12 Javascript
如何在父窗口中得知window.open()出的子窗口关闭事件
2013/10/15 Javascript
javascript常用经典算法实例详解
2015/11/25 Javascript
JS 实现Base64编码与解码实例详解
2016/11/07 Javascript
jQuery联动日历的实例解析
2016/12/02 Javascript
jQuery插件HighCharts绘制2D柱状图、折线图的组合双轴图效果示例【附demo源码下载】
2017/03/09 Javascript
angular中实现控制器之间传递参数的方式
2017/04/24 Javascript
vue2.0+ 从插件开发到npm发布的示例代码
2018/04/28 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
对vuex中getters计算过滤操作详解
2019/11/06 Javascript
ReactRouter的实现方法
2021/01/25 Javascript
[02:54]辉夜杯主赛事第二日败者组 iG.V赛后采访
2015/12/26 DOTA
[01:28]国服启动器接入蒸汽平台操作流程视频
2021/03/11 DOTA
python中使用urllib2伪造HTTP报头的2个方法
2014/07/07 Python
Python 数据结构之旋转链表
2017/02/25 Python
Tensorflow 查看变量的值方法
2018/06/14 Python
Python通用循环的构造方法实例分析
2018/12/19 Python
对Python中的条件判断、循环以及循环的终止方法详解
2019/02/08 Python
linux环境中没有网络怎么下载python
2019/07/07 Python
详解用 python-docx 创建浮动图片
2021/01/24 Python
法国时尚品牌乐都特瑞士站:La Redoute瑞士
2016/09/05 全球购物
对象的序列化(serialization)类是面向流的,应如何将对象写入到随机存取文件中
2015/06/22 面试题
中文专业毕业生自荐信
2013/10/28 职场文书
英文简历中的自我评价用语
2013/12/09 职场文书
代办委托书怎样写
2014/04/08 职场文书
高效课堂标语
2014/06/26 职场文书
土地租赁意向书
2014/07/30 职场文书
高校师德师风自我剖析材料
2014/09/29 职场文书
培训班通知
2015/04/25 职场文书
项目验收申请报告
2015/05/15 职场文书
python 爬取天气网卫星图片
2021/06/07 Python
CSS实现隐藏搜索框功能(动画正反向序列)
2021/07/21 HTML / CSS
Java9新特性之Module模块化编程示例演绎
2022/03/16 Java/Android