D3.js实现直方图的方法详解


Posted in Javascript onSeptember 25, 2016

一、直方图简介

直方图就是一种照片的分析方式,横向代表亮度,纵向代表像素数量。首先分析出照片中所有像素的亮度,然后计算出具体数值,再把它们映射到横轴上。这样的话,越高,这个亮度上的像素就越多。

直方图的观看规则就是“左黑右白”,左边代表暗部,右边代表亮部,而中间则代表中间调。

纵向上的高度代表像素密集程度,越高,代表的就是分布在这个亮度上的像素很多。

直方图用于描述概率分布,D3 提供了直方图的布局 Histogram 用于转换数据。

D3.js实现直方图的方法详解

假设有数组 a = [10, 11, 11.5, 12.5, 13, 15, 19, 20 ],现在把10~20的数值范围分为5段,即:

10~12, 12~14, 14~16, 16~18, 18~20

那么数组 a 的各数值都落在这几段区域的哪一部分呢?经过计算,可以知道,这5段分别具有的元素个数为:

3, 2, 1, 0 , 2

将这个用图形展示出来的,就是直方图。

好了,开始制作吧~

二、数据

首先生成随机数据:

var rand = d3.random.normal(0,25); 
var dataset = []; 
for(var i=0;i<100;i++){ 
 dataset.push( rand() ); 
}

d3.random.normal 生成一个函数,这个函数能够按正态(高斯)分布随机生成数值。要传入两个参数,第一个是位置参数,第二个是尺寸参数。关于正态分布的定义,可参见维基百科。将这个函数赋值给 rand 之后,接下来只要用 rand() 即可生成随机数。

三、布局(数据转换)

接下来,要将上述数据进行转换,即确定一个区间和分隔数之后,另数组的数值落在各区域里。先定义一个布局:

var bin_num = 15; 
var histogram = d3.layout.histogram() 
   .range([-50,50]) 
    .bins(bin_num) 
   .frequency(true);

d3.layout.histogram: 直方图的布局

range: 区间的范围

bins: 分隔数

frequency: 若值为 true,则统计的是个数;若值为 false,则统计的是概率

接下来即可转换数据:

var data = histogram(dataset);

来看看转换前后的数据有什么分别吧。转换前:

D3.js实现直方图的方法详解

转换后:

D3.js实现直方图的方法详解

可以看到,转换后的数组,长度即分隔数,每一个区间内有落到此区间的数值(图中的0,1,2,...),数值的个数(length),还

有三个参数:

x: 区间的起始位置

dx: 区间的宽度

y: 落到此区间的数值的数量(如果 frequency 为 true);落到此区间的概率(如果 frequency 为 false)

四、绘制

绘制之前,需要定义一个比例尺,因为通常我们需要让转换后的 y 在希望的范围内伸缩。

var max_height = 400; 
var rect_step = 30; 
var heights = []; 
for(var i=0;i<data.length;i++){ 
 heights.push( data[i].y ); 
} 
var yScale = d3.scale.linear() 
     .domain([d3.min(heights),d3.max(heights)]) 
     .range([0,max_height]);

最后,绘制图形:

//绘制图形 
var graphics = svg.append("g") 
     .attr("transform","translate(30,20)"); 
 
//绘制矩形 
graphics.selectAll("rect") 
  .data(data) 
  .enter() 
  .append("rect") 
  .attr("x",function(d,i){ 
   return i * rect_step; 
  }) 
  .attr("y", function(d,i){ 
   return max_height - yScale(d.y); 
  }) 
  .attr("width", function(d,i){ 
   return rect_step - 2; 
  }) 
  .attr("height", function(d){ 
   return yScale(d.y); 
  }) 
  .attr("fill","steelblue"); 
 
//绘制坐标轴的直线 
graphics.append("line") 
  .attr("stroke","black") 
  .attr("stroke-width","1px") 
  .attr("x1",0) 
  .attr("y1",max_height) 
  .attr("x2",data.length * rect_step) 
  .attr("y2",max_height); 
 
//绘制坐标轴的分隔符直线 
graphics.selectAll(".linetick") 
  .data(data) 
  .enter() 
  .append("line") 
  .attr("stroke","black") 
  .attr("stroke-width","1px") 
  .attr("x1",function(d,i){ 
   return i * rect_step + rect_step/2; 
  }) 
  .attr("y1",max_height) 
  .attr("x2",function(d,i){ 
   return i * rect_step + rect_step/2; 
  }) 
  .attr("y2",max_height + 5); 
 
//绘制文字 
graphics.selectAll("text") 
  .data(data) 
  .enter() 
  .append("text") 
  .attr("font-size","10px") 
  .attr("x",function(d,i){ 
   return i * rect_step; 
  }) 
  .attr("y", function(d,i){ 
   return max_height; 
  }) 
  .attr("dx",rect_step/2 - 8) 
  .attr("dy","15px") 
  .text(function(d){ 
   return Math.floor(d.x); 
  });

五、总结

以上就是这篇文章的全部内容了,希望能对大家的学习或者工作带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
JavaScript中使用正则匹配多条,且获取每条中的分组数据
Nov 30 Javascript
jquery 鼠标滑动显示详情应用示例
Jan 24 Javascript
javascript浏览器窗口之间传递数据的方法
Jan 20 Javascript
JavaScript实现动画打开半透明提示层的方法
Apr 21 Javascript
JQuery实现图片轮播效果
Sep 15 Javascript
js轮播图代码分享
Jul 14 Javascript
微信小程序 slider 详解及实例代码
Jan 10 Javascript
Javascript实现的StopWatch功能示例
Jun 13 Javascript
js获取地址栏参数的两种方法
Jun 27 Javascript
vue.js分页中单击页码更换页面内容的方法(配合spring springmvc)
Feb 10 Javascript
使用 vue-i18n 切换中英文效果
May 23 Javascript
JS实现斐波那契数列的五种方式(小结)
Sep 09 Javascript
关于JS中二维数组的声明方法
Sep 24 #Javascript
js日期相关函数dateAdd,dateDiff,dateFormat等介绍
Sep 24 #Javascript
浅谈JS中的!=、== 、!==、===的用法和区别
Sep 24 #Javascript
让DIV的滚动条自动滚动到最底部的3种方法(推荐)
Sep 24 #Javascript
浅谈js常用内置方法和对象
Sep 24 #Javascript
js原生跨域_用script标签的简单实现
Sep 24 #Javascript
js内置对象处理_打印学生成绩单的简单实现
Sep 24 #Javascript
You might like
非洲第一个咖啡超凡杯大赛承办国—卢旺达的咖啡怎么样
2021/03/03 咖啡文化
php数组添加元素方法小结
2014/12/20 PHP
PHP连接MSSQL时nvarchar字段长度被截断为255的解决方法
2014/12/25 PHP
php相对当前文件include其它文件的方法
2015/03/13 PHP
深入理解PHP变量的值类型和引用类型
2015/10/21 PHP
PHP getallheaders无法获取自定义头(headers)的问题
2016/03/23 PHP
PHP序列化/对象注入漏洞分析
2016/04/18 PHP
ThinkPHP实现转换数据库查询结果数据到对应类型的方法
2017/11/16 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
Discuz不使用插件实现简单的打赏功能
2019/03/21 PHP
40款非常棒的jQuery 插件和制作教程(系列一)
2011/10/26 Javascript
jquery对单选框,多选框,文本框等常见操作小结
2014/01/08 Javascript
谷歌地图打不开的解决办法
2014/08/07 Javascript
iframe里使用JavaScript控制主页转向的方法
2015/04/03 Javascript
使用javascript提交form表单方法汇总
2015/06/25 Javascript
JS实现图片高亮展示效果实例
2015/11/24 Javascript
Bootstrap多级导航栏(级联导航)的实现代码
2016/03/08 Javascript
JS实现图片延迟加载并淡入淡出效果的简单方法
2016/08/25 Javascript
基于jQuery实现左侧菜单栏可折叠功能
2016/12/27 Javascript
@ResponseBody 和 @RequestBody 注解的区别
2017/03/08 Javascript
jquery select插件异步实时搜索实例代码
2017/10/20 jQuery
详解js中Array的方法及技巧
2018/09/12 Javascript
JavaScript实现矩形块大小任意缩放
2020/08/25 Javascript
vue移动端写的拖拽功能示例代码
2020/09/09 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
[50:22]完美盛典-2018年度红毯走秀
2018/12/16 DOTA
Python使用pickle模块报错EOFError Ran out of input的解决方法
2018/08/16 Python
python 动态生成变量名以及动态获取变量的变量名方法
2019/01/20 Python
Python partial函数原理及用法解析
2019/12/11 Python
在python中使用pymysql往mysql数据库中插入(insert)数据实例
2020/03/02 Python
python数据抓取3种方法总结
2021/02/07 Python
飞利浦比利时官方网站:Philips比利时
2016/08/24 全球购物
华美博弈C/VC工程师笔试试题
2012/07/16 面试题
党员违纪检讨书
2014/02/18 职场文书
办公用品管理制度
2015/08/04 职场文书
iPhone13 Pro外观确定,升级4800万镜头,4月20日发新品
2021/04/15 数码科技