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 TextBox自动完成条
Jul 22 Javascript
js 分栏效果实现代码
Aug 29 Javascript
js动画效果制件让图片组成动画代码分享
Jan 14 Javascript
jQuery 2.0.3 源码分析之core(一)整体架构
May 27 Javascript
JS实现的用来对比两个用指定分隔符分割的字符串是否相同
Sep 19 Javascript
JS实现仿QQ效果的三级竖向菜单
Sep 25 Javascript
Jquery获取第一个子元素简单实例
Jun 02 Javascript
JS基础随笔(菜鸟必看篇)
Jul 13 Javascript
微信小程序数字滚动插件使用详解
Feb 02 Javascript
Vue + better-scroll 实现移动端字母索引导航功能
May 07 Javascript
Nuxt.js 静态资源和打包的操作
Nov 06 Javascript
详解Vue3.0 + TypeScript + Vite初体验
Feb 22 Vue.js
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作的文本留言本的例子(五)
2006/10/09 PHP
php使用mkdir创建多级目录入门例子
2014/05/10 PHP
使用GDB调试PHP代码,解决PHP代码死循环问题
2015/03/02 PHP
让JavaScript 轻松支持函数重载 (Part 1 - 设计)
2009/08/04 Javascript
jQuery+CSS 实现的超Sexy下拉菜单
2010/01/17 Javascript
事件模型在各浏览器中存在差异
2010/10/20 Javascript
jquery 学习之二 属性(类)
2010/11/25 Javascript
Underscore.js 的模板功能介绍与应用
2012/12/24 Javascript
extjs4 treepanel动态改变行高度示例
2013/12/17 Javascript
jQuery模拟黑客帝国矩阵效果实例
2015/06/28 Javascript
javascript每日必学之运算符
2016/02/16 Javascript
Javascript简写条件语句(推荐)
2016/06/12 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
2017/03/27 Javascript
JS实现常见的查找、排序、去重算法示例
2018/05/21 Javascript
layer实现登录弹框,登录成功后关闭弹框并调用父窗口的例子
2019/09/11 Javascript
javascript设计模式 ? 抽象工厂模式原理与应用实例分析
2020/04/09 Javascript
[04:30]显微镜下的DOTA2第五期——拉比克
2013/09/26 DOTA
Python将多个excel表格合并为一个表格
2021/02/22 Python
python时间日期函数与利用pandas进行时间序列处理详解
2018/03/13 Python
python 实现将小图片放到另一个较大的白色或黑色背景图片中
2019/12/12 Python
学python最电脑配置有要求么
2020/07/05 Python
AmazeUI 模态窗口的实现代码
2020/08/18 HTML / CSS
VICHY薇姿英国官网:全球专业敏感肌护肤领先品牌
2017/07/04 全球购物
乔丹诺(Giordano)酒庄德国官网:找到最好的意大利葡萄酒
2017/12/28 全球购物
FLOS美国官网:意大利高级照明工艺的传奇
2018/08/07 全球购物
意大利自行车商店:Cingolani Bike Shop
2019/09/03 全球购物
《燕子专列》教学反思
2014/02/21 职场文书
交通安全寄语大全
2014/04/08 职场文书
建筑工程造价专业自荐信
2014/07/08 职场文书
2014小学语文教师个人工作总结
2014/12/03 职场文书
荆州古城导游词
2015/02/06 职场文书
走近毛泽东观后感
2015/06/04 职场文书
Python基础数据类型tuple元组的概念与用法
2021/08/02 Python
mybatis中注解与xml配置的对应关系和对比分析
2021/08/04 Java/Android
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers
win10双系统怎么删除一个系统?win10电脑有两个系统删除一个的操作方法
2022/07/15 数码科技