比例尺

比例尺基本内容

比例尺是一组把输入域映射为输出范围的函数。任意数据集中的值不可能恰好与图表中的像素尺度一一对应。比例尺就是把这些数据值映射为可视化图形中使用的新值的便捷手段。D3的比例尺就是那些你定义的带有参数的函数。定义好之后,就可以调用这些比例尺函数,传入值,它们就能返回按比例生成的输出值。
比例尺的输入值域(input domain)指可能的输入值的范围。
比例尺的输出范围(output range)指输出值可能的范围,一般以用于显示的像素为 单位。
其实比例尺就是归一化的概念。
D3有一个比例尺函数生成器,通过d3.scale来访问。要生成一个比例尺,在d3.scale后面加上要创建的比例尺类型即可。
var scale = d3.scale.linear();
设置比例尺的值域需要调用domain()方法,并将值域以数组形式传给它。假设值域是100到500,那么就可以这样写代码: 
scale.domain([100, 500]);   
设定输出范围的方式类似,但要调用range()方法:
scale.range([10, 350]);
如果不想给值域设置固定的值,那可以使用两个方便的数组函数:d3.min()和 d3.max(),让它们帮你动态分析数据集。
vardataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
];
d3.max(dataset, function(d) {
return d[0];
});
这个存取器函数是一个匿名函数,max()会把数组中的每个元素(即这里的d)交给它。存取器函数的目的是指定比较哪个值。对我们的数据集而言,需要比较x值, 也就是嵌套数组的第一个值,位置为0。把我们刚刚介绍的知识综合起来,就可以创建一个动态映射x轴值的比例尺函数:
varxScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([0, 300]);

其它比例尺

除了线性(linear)比例尺,D3还内置了另外几个比例尺方法。
sqrt 
平方根比例尺。
pow 
幂比例尺,适合值以指数级变化的数据集。
log 
对数比例尺。
quantize 
输出范围为独立的值的线性比例尺,适合想把数据分类的情形。
quantile 
与quantize类似,但输入值域是独立的值,适合已经对数据分类的情形。
ordinal 
使用非定量值(如类名)作为输出的序数比例尺,非常适合比较苹果和桔子。
d3.scale.category10()  、d3.scale.category20()、d3.scale.category20b()和d3.scale.category20c()
能够输出10到20种类别颜色的预设序数比例尺,非常方便。
d3.time.scale() 
针对日期和时间值的一个比例尺方法,可以对日期刻度作特殊处理。 领略了比例尺的威力之后,该通过一些东西来表达它们了,通过什么呢?对, 数轴!

数轴

设定数轴

与比例尺相似,D3的数轴实际上也是由你来定义参数的函数。但与比例尺不同的是,调用数轴函数并不会返回值,而是会生成数轴相关的可见元素,包括轴线、标签和刻度。
使用d3.svg.axis()可以创建通用的数轴函数:
var xAxis = d3.svg.axis();
要使用数轴,最起码要告诉它基于什么比例尺工作。在此,我们把绘制散点图时定义的xScale传给它: 
xAxis.scale(xScale);
还可以继续设置标签相对数轴显示在什么地方。默认位置是底部,也就是标签会出现在轴线下方。水平数轴的位置可 以在顶部也可以在底部。而垂直数轴则要么在左要么在右: 
xAxis.orient("bottom");
把这些方法连缀在一行会更简洁:
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
SVG中的其他元素都生成之后再生成数轴,这样数轴就可以出现在“上面了。想要生成数轴还要调用xAxis函数将其插入到svg元素中。
svg.append("g")
.call(xAxis);
 前面的代码首先引用了svg,即DOM中的SVG元素。然后,append()在 这个元素的末尾追加了一个新的g元素。在SVG标签内,g元素就是一个分组(group)元素。分组元素是不可见的,跟line、rect和circle不一样,但它有两大用途:一是可以用来包含(或“组织”)其他元素,好让代码看起来简洁整齐;二是可以对整个分组应用变换,从而影响到该组中所有元素(line、rect和
circle)的视觉表现。D3的call()函数会取得(比如刚才代码链中)传递过来的元素,然后再把它交给其他函数。对我们这例子而言,传递过来的元素就是新的分组元素g(虽然这个元素不是必需的,但鉴于数轴函数需要生成很多线条和数值,有了它就可以把所有元素都封装在一个分组对象内)。而call()接着把g交给了xAxis函数,也就是要 在g元素里面生成数轴。
就该用到SVG变换(transform)了。只要添加一行代码,就可以把整个数轴分组平移到图表下方: 
svg.append("g") .attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis);
新增的这行代码在attr()中设置了g元素的属性transform。SVG中的变换功 能非常强大,有多种不同的变换方式,包括缩放和旋转。但我们暂时只介绍平移 (translation)变换,它可以把整个g分组向下移动一定距离。平移变换的语法很简单,就是translate(x,y),其中x和y的含义都非常明确, 就是要把元素移动到的新位置的x和y坐标。

优化刻度

数轴的刻度线(tick)是用来传达信息的,但也不是越多越好,多过某个数量,刻度线反而会让图表显得混乱。使用ticks()方法就可以粗略地指定刻 度线的数量: 
varxAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5); //粗略地设置刻度线的数量

一个简单的散点图

//svg的宽度和高度
var w = 500;
var h = 300;
var padding = 30;
//初始化数据点
var dataset = [];
var numDataPoints = 15;
//x轴最大的数值
var xRange = Math.random() * 1000;
//y轴最大的数值
var yRange = Math.random() * 1000;
for (var i = 0; i < numDataPoints; i++) {
var newNumber1 = Math.floor(Math.random() * xRange);
var newNumber2 = Math.floor(Math.random() * yRange);
dataset.push([newNumber1, newNumber2]);
}
//创建刻度尺
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - padding, padding]);
var rScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([2, 5]);
//定义x轴
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5);
//定义y轴
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//创建svg元素
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//创建圆形
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return rScale(d[1]);
});
//创建标签
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
return yScale(d[1]);
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red"); //将x轴追加到g元素中
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis); //将y轴追加到g元素中
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
其中坐标轴的css如下,这里需要注意的是,坐标轴是由text、line和path构成的:
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
} .axis text {
font-family: sans-serif;
font-size: 11px;
}

最终效果如下图所示:



d3.js读书笔记-2的更多相关文章

  1. d3.js读书笔记-1

    d3.js入门 d3入门 D3是一个强大的数据可视化工具,它是基于Javascript库的,用于创建数据可视化图形.在生成可视化图形的过程中,需要以下几步: 把数据加载到浏览器的内存空间: 把数据绑定 ...

  2. js读书笔记

    js读书笔记 基本类型的基本函数总结 1. Boolean() 数据类型 转换为true的值 转换为false的值 Boolean true false String 任何非空字符串 "&q ...

  3. D3.js学习笔记(六)——SVG基础图形和D3.js

    目标 在这一章,我们将会重温SVG图形,学习如何使用D3.js来创建这些图形. 这里会包括前面例子中的SVG基础图形以及如何使用D3.js设置图形的属性. 使用D3.js画一个SVG 的 圆 circ ...

  4. d3.js学习笔记(五)——将数据结构化为D3.js可处理的

    目标 在这一章,你将会理解如何对数据进行结构化,来更好的使用D3.js. 我们将会回顾我们之前已经学习的,学习D3.js如何使用选集(selections),JavaScript对象基础,以及如何最优 ...

  5. D3.js学习笔记(四)—— 使用SVG坐标空间

    目标 在这一章,你将要使用D3.js基于一些数据把SVG元素添加到你想要的坐标位置上. 我们的目标就是使用下面的数据集: var spaceCircles = [30,70,110]; 并使用D3.j ...

  6. D3.js学习笔记(三)——创建基于数据的SVG元素

    目标 在这一章,你将会使用D3.js,基于我们的数据来把SVG元素添加到网页中.这一过程包括:把数据绑定到元素上,然后在使用这些元素来可视化我们的数据. 注意:不同于前几章,我们从一个完整的代码开始, ...

  7. D3.js学习笔记(二)——使用绑定在DOM上的数据

    简单例子 在这个例子中,你将会使用D3.js来将数据绑定到DOM元素上.然后再使用D3.js利用绑定到DOM元素上的数据来更新网页. 在上一章中,我们以下面这个页面作为开始的: <!DOCTYP ...

  8. D3.js学习笔记(一)——DOM上的数据绑定

    开始学习D3.js,网上没有找到很满意的中文教程,但是发现了一个很好的英文教程,讲解的非常详细.从一个初始简单的HTML网页开始,逐步加入D3.js的应用,几乎是逐句讲解.学习的时候,就顺便翻译成中文 ...

  9. 精通D3.js学习笔记(2)比例尺和坐标

    1.线性比例尺 d3.scale.linear()   创建一个线性比例尺           .domain([0,500]) 定义域           .range([0,1000]) 值域 l ...

随机推荐

  1. 初测WIN10

    WIN10已经发布,通过百度直通车把WIN7升级成了WIN10,改变较大,不太习惯,用着不是很顺手. 吐槽几个问题 1.微软的Visual Studio 2015 Community版本,宣布是免费的 ...

  2. git中手动删除的文件如何在git中删除

    在日常开发中,我们可能或手动删除(delete键删除的)一些文件,然而我们本来应该是用git rm fileName命令删除的,但是现在我们手动删除了,那么要如何在git里面讲那些手动删除的文件删除呢 ...

  3. C# 文件读写异常“正由另一进程使用,因此该进程无法访问该文件”

    最近在对文件进行读写操作时,利用using的方法可还是遇到了异常"文件正由另一进程使用,因此该进程无法访问该文件": public bool WriteUserInfo(strin ...

  4. JDBC操作数据库的三种方式比较

    JDBC(java Database Connectivity)java数据库连接,是一种用于执行上sql语句的javaAPI,可以为多种关系型数据库提供统一访问接口.我们项目中经常用到的MySQL. ...

  5. Spring保护方法

    Spring保护方法 一.使用注解保护方法 1.@Secured 由Spring Security提供,首先需要启用基于注解的方法安全性: @EnableGlobalMethodSecurity(se ...

  6. 思维导图软件 xMind 基本用法

    官方下载:https://www.xmind.net/download/win/ 官方快捷键说明:https://www.xmind.net/blog/cn/tag/xmind%EF%BC%8C%E5 ...

  7. Scala_基本语法

    基本语法 声明值和变量 Scala有两种类型的变量: val:是不可变的(变量的引用不可变),在声明时就必须被初始化,而且初始化以后就不能再赋值: var:声明的时候需要进行初始化,初始化以还可以再对 ...

  8. python&#39;s os.system&amp;os.spawn

    [python's os.system&os.spawn] os.system会新建一个子shell,在子shell中执行传入的sh脚本.os.spawn用于执行一个bin,产生一个子进程.所 ...

  9. [BZOJ4784][ZJOI2017]仙人掌(树形DP)

    4784: [Zjoi2017]仙人掌 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 312  Solved: 181[Submit][Status] ...

  10. python socket和简单tcp通信实现

    python 服务端和客户端的简单交互 TCP服务端: 1 创建套接字,绑定套接字到本地IP与端口 s = socket.socket(socket.AF_INET,socket.SOCK_STREA ...