D3.js实现散点图和气泡图的方法详解


Posted in Javascript onSeptember 21, 2016

前言

小编之前已经跟大家分享过了《D3.js实现柱状图的方法详解》和《D3.js实现折线图的方法详解》这两篇文章,已经介绍过柱状图和折线图了。下面就来说说和这两种非常相似的图表——散点图和气泡图。有需要的朋友们可以参考学习。

散点图和气泡图的实现

还是和之前一样,我们先把简单的画图框架搭起来,添加SVG画布:

<!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="d3/d3.js"></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>

散点图和气泡图虽然在展现意义上是不同的,但从技术实现的角度来讲,它们还是很类似的,都是由坐标轴和一个个的圆所组成的。

散点图

坐标轴的实现

为了实现真实的效果,散点图和气泡图我们使用不同的模拟数据。与折线图同理,散点图的各点的坐标的关系在坐标轴上的关系是连续的,所以它的x轴和y轴都使用线性比例尺(线性比例尺和序数比例尺的区别参见《D3.js实现柱状图的方法详解》)。

// 模拟数据
var dataset = [[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],
  [170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],
  [172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],
  [147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],
  [159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],
  [174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],
  [154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],
  [162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],
  [168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],
  [167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],
  [167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],
  [168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],
  [156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],
  [162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],
  [151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],
  [164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],
  [170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],
  [163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],
  [161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],
  [159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],
  [161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],
  [171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],
  [166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],
  [159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],
  [162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],
  [172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],
  [162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],
  [158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],
  [167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],
  [170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],
  [160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],
  [166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],
  [170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],
  [167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],
  [160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],
  [177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],
  [172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],
  [175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],
  [165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],
  [168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],
  [162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],
  [157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],
  [172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],
  [161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],
  [152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],
  [160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],
  [167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],
  [175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],
  [174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],
  [156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],
  [169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],
  [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]
 ];
// 创建x轴的比例尺
var xScale = d3.scale.linear()
 .domain([140, 190])
 .range([0, width - padding.left - padding.right]);
// 创建y轴的比例尺
var yScale = d3.scale.linear()
 .domain([40, 120])
 .range([height - padding.top - padding.bottom, 0]);
// 创建x轴
var xAxis = d3.svg.axis()
 .scale(xScale)
 .orient('bottom');
// 创建y轴
var yAxis = d3.svg.axis()
 .scale(yScale)
 .orient('left');
// 把x轴应用到对应的SVG元素上
main.append('g')
 .attr('class', 'axis')
 .attr('transform', 'translate(0,' + (height - padding.top - padding.bottom) + ')')
 .call(xAxis);
// 把y轴应用到对应的SVG元素上
main.append('g')
 .attr('class', 'axis')
 .call(yAxis);

同折线图的坐标轴的实现是相同的,先用d3.scale.linear()创建比例尺,再用d3.svg.axis()创建坐标轴并且设置对应的比例尺,最后添加SVG元素并“绑定”坐标轴到其上,就可以看到完成以后的坐标轴。注意这里需要对移动SVG元素,使它们在视觉上组装成一个坐标系(但实际上它们在位置上是零散的,并没有很强的关系)。

D3.js实现散点图和气泡图的方法详解

散点的实现

在图表中一般点都是通过画圆来实现的,当圆的半径足够小的时候,它就是点。

// 添加散点
main.selectAll('.point')
 .data(dataset)
 .enter()
 .append('circle')
 .attr('class', 'point')
 .attr('cx', function(d) {
  return xScale(d[0]);
 })
 .attr('cy', function(d) {
  return yScale(d[1]);
 })
 .attr('r', 5);

与折线图添加点的方式是一样的。在main元素中选择到所有的圆先“占位”(因为此时选择到的是一个空的集合,只是这个集合代表main中所有的圆),然后绑定dataset到此集合上,通过enter()append()搭配使用添加新的circle元素直到集合元素个数与dataset子元素个数相同为止。用比例尺计算出各圆的坐标并对其相关属性进行赋值,就完成了点的添加。因为散点图的点有点多,为了图表更加美观,给圆设置一下样式。

.point {
 fill: #2ec7c9;
 fill-opacity: 0.5;
}

最后,散点图长这样。

D3.js实现散点图和气泡图的方法详解

气泡图

坐标轴的实现

因为只有模拟的数据结构不同,实现原理都是类似的,这里就不再赘述,直接上代码。

// 模拟数据
var dataset = [
 { x: 69, y: 45, weight: 5 },{ x: 30, y: 37, weight: 10 },
 { x: 43, y: 10, weight: 23 },{ x: 54, y: 48, weight: 41 },
 { x: 18, y: 18, weight: 41 },{ x: 88, y: 21, weight: 32 },
 { x: 45, y: 48, weight: 12 },{ x: 14, y: 32, weight: 9 },
 { x: 78, y: 18, weight: 16 },{ x: 13, y: 45, weight: 32 }
];
// 添加x轴和y轴
var xScale = d3.scale.linear()
 .domain([0, 100])
 .range([0, width - padding.left - padding.right]);
var yScale = d3.scale.linear()
 .domain([0, 50])
 .range([height - padding.top - padding.bottom, 0]);
var xAxis = d3.svg.axis()
 .scale(xScale)
 .orient('bottom');
var yAxis = d3.svg.axis()
 .scale(yScale)
 .orient('left');

气泡的实现

// 添加气泡
main.selectAll('.bubble')
 .data(dataset)
 .enter()
 .append('circle')
 .attr('class', 'bubble')
 .attr('cx', function(d) {
  return xScale(d.x);
 })
 .attr('cy', function(d) {
  return yScale(d.y);
 })
 .attr('r', function(d) {
  return d.weight;
 });

最后的气泡图是长这样的。

D3.js实现散点图和气泡图的方法详解

总结

以上就是利用D3.js实现散点图和气泡图的全部内容,希望这篇文章对大家的学习和工作能有所帮助。小编还会陆续更新关于D3.js的文章,请大家继续关注三水点靠木,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
面向对象的Javascript之二(接口实现介绍)
Jan 27 Javascript
js 判断checkbox是否选中的操作方法
Nov 09 Javascript
Jquery 数组操作大全个人总结
Nov 13 Javascript
jquery获取文档高度和窗口高度汇总
Jan 25 Javascript
将List对象列表转换成JSON格式的类实现方法
Jul 04 Javascript
jquery判断类型是不是number类型的实例代码
Oct 07 Javascript
利用JS判断鼠标移入元素的方向
Dec 11 Javascript
微信小程序中hidden不生效原因的解决办法
Apr 26 Javascript
JavaScript编程设计模式之构造器模式实例分析
Oct 25 Javascript
解决vue项目报错webpackJsonp is not defined问题
Mar 14 Javascript
详解ECMAScript typeof用法
Jul 25 Javascript
js实现导航跟随效果
Nov 17 Javascript
AngularJs ng-repeat 嵌套如何获取外层$index
Sep 21 #Javascript
D3.js实现饼状图的方法详解
Sep 21 #Javascript
angularJS Provider、factory、service详解及实例代码
Sep 21 #Javascript
JS实现图文并茂的tab选项卡效果示例【附demo源码下载】
Sep 21 #Javascript
AngularJS ngModel实现指令与输入直接的数据通信
Sep 21 #Javascript
D3.js实现折线图的方法详解
Sep 21 #Javascript
利用BootStrap弹出二级对话框的简单实现方法
Sep 21 #Javascript
You might like
PHP云打印类完整示例
2016/10/15 PHP
javascript 简练的几个函数
2009/08/29 Javascript
node.js中的buffer.slice方法使用说明
2014/12/10 Javascript
JQuery简单实现锚点链接的平滑滚动
2015/05/03 Javascript
快速掌握WordPress中加载JavaScript脚本的方法
2015/12/17 Javascript
Angularjs全局变量被作用域监听的正确姿势
2016/02/06 Javascript
原生js实现焦点轮播图效果
2017/01/12 Javascript
Extjs gridpanel 中的checkbox(复选框)根据某行的条件不能选中的解决方法
2017/02/17 Javascript
jQuery实现IE输入框完成placeholder标签功能的方法
2017/09/20 jQuery
js 客户端打印html 并且去掉页眉、页脚的实例
2017/11/03 Javascript
AngularJS 应用模块化的使用
2018/04/04 Javascript
JS实现根据指定值删除数组中的元素操作示例
2018/08/02 Javascript
一文快速了解JQuery中的AJAX
2019/05/31 jQuery
JS pushlet XMLAdapter适配器用法案例解析
2020/10/16 Javascript
[54:56]DOTA2上海特级锦标赛主赛事日 - 5 总决赛Liquid VS Secret第三局
2016/03/06 DOTA
vc6编写python扩展的方法分享
2014/01/17 Python
打包发布Python模块的方法详解
2016/09/18 Python
Python使用PyCrypto实现AES加密功能示例
2017/05/22 Python
Python爬虫之模拟知乎登录的方法教程
2017/05/25 Python
Python比较2个时间大小的实现方法
2018/04/10 Python
Python虚拟环境的原理及使用详解
2019/07/02 Python
python 正则表达式参数替换实例详解
2020/01/17 Python
Django视图、传参和forms验证操作
2020/07/15 Python
pandas使用函数批量处理数据(map、apply、applymap)
2020/11/27 Python
Etam艾格英国官网:法国著名女装品牌
2019/04/15 全球购物
商场拾金不昧表扬信
2014/01/13 职场文书
客户接待方案
2014/02/26 职场文书
金融管理专业毕业生求职信
2014/03/12 职场文书
升旗仪式主持词
2014/03/19 职场文书
政府门卫岗位职责
2014/04/29 职场文书
党的群众路线教育实践活动整改方案
2014/10/28 职场文书
党的群众路线教育实践活动心得体会(医院)
2014/11/03 职场文书
新教师个人总结
2015/02/06 职场文书
开会通知
2015/04/20 职场文书
八年级语文教学反思
2016/03/03 职场文书
Apache POI操作批量导入MySQL数据库
2022/06/21 Servers