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 相关文章推荐
jQuery 动画基础教程
Dec 25 Javascript
Javascript document.referrer判断访客来源网址
May 15 Javascript
高性能web开发 如何加载JS,JS应该放在什么位置?
May 14 Javascript
jQuery实战之仿淘宝商城左侧导航效果
Apr 12 Javascript
jQuery移除元素自动解绑事件实现思路及代码
May 31 Javascript
JS生成不重复随机数组的函数代码
Jun 10 Javascript
学习Bootstrap组件之下拉菜单
Jul 28 Javascript
javascript常用的方法整理
Aug 20 Javascript
每天一篇javascript学习小结(属性定义方法)
Nov 19 Javascript
Javascript 引擎工作机制详解
Nov 30 Javascript
微信小程序上传图片实例
May 28 Javascript
vue.js封装switch开关组件的操作
Oct 26 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桌面中心(一) 创建数据库
2007/03/11 PHP
php下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
laravel框架数据库配置及操作数据库示例
2019/10/10 PHP
动态的绑定事件addEventListener方法的使用
2014/01/24 Javascript
无刷新预览所选择的图片示例代码
2014/04/02 Javascript
jQuery $.extend()用法总结
2014/06/15 Javascript
jQuery图片切换插件jquery.cycle.js使用示例
2014/06/16 Javascript
javascript实现简单的进度条
2015/07/02 Javascript
详解NodeJS框架express的路径映射(路由)功能及控制
2017/03/24 NodeJs
JS实现颜色的10进制转化成rgba格式的方法
2017/09/04 Javascript
jQuery实现的粘性滚动导航栏效果实例【附源码下载】
2017/10/19 jQuery
Angular实现的日程表功能【可添加及隐藏显示内容】
2017/12/27 Javascript
nodejs 最新版安装npm 的使用详解
2018/01/18 NodeJs
详解小程序原生使用ES7 async/await语法
2018/08/06 Javascript
简谈创建React Component的几种方式
2019/06/15 Javascript
解决Vue动态加载本地图片问题
2019/10/09 Javascript
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
[36:02]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第一局
2016/02/28 DOTA
[41:52]2018DOTA2亚洲邀请赛3月29日小组赛B组Effect VS Secret
2018/03/30 DOTA
[03:43]TI9战队采访——PSG.LGD
2019/08/22 DOTA
Python中itertools模块用法详解
2014/09/25 Python
python 处理数字,把大于上限的数字置零实现方法
2019/01/28 Python
Python imageio读取视频并进行编解码详解
2019/12/10 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
2020/04/15 Python
django filter过滤器实现显示某个类型指定字段不同值方式
2020/07/16 Python
美国一家主营日韩美妆护肤品的在线商店:iMomoko
2016/09/11 全球购物
商业融资计划书
2014/04/29 职场文书
防沙治沙典型材料
2014/05/07 职场文书
志愿者活动总结报告
2014/06/27 职场文书
律师授权委托书范本
2014/10/07 职场文书
2014年公路养护工作总结
2014/12/04 职场文书
一年级数学下册复习计划
2015/01/17 职场文书
2016春节家属慰问信
2015/03/25 职场文书
公司人力资源管理制度
2015/08/05 职场文书
Oracle笔记
2021/04/05 Oracle
在前女友婚礼上,用Python破解了现场的WIFI还把名称改成了
2021/05/28 Python