比例尺

比例尺基本内容

比例尺是一组把输入域映射为输出范围的函数。任意数据集中的值不可能恰好与图表中的像素尺度一一对应。比例尺就是把这些数据值映射为可视化图形中使用的新值的便捷手段。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. C学习笔记 知识集锦(一)

    1.标识符  2.寄存器变量 3.全局变量 4.分配内存与初始化 5.变量定义与声明 6.作用域规则 跳转语句 7.&与&&,|和||的意义与区别 8.如何选择switch c ...

  2. 分享一组矢量图标–UX图标字体库

    以下内容转自:http://ux.etao.com/,原文链接:http://ued.alimama.com/posts/219 科技日新月异的今天,市面上各种分辨率.各种显示精度的显示设备层出不穷, ...

  3. (转)HTTP 长连接和短连接

    1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问 ...

  4. Spark&Hive:如何使用scala开发spark访问hive作业,如何使用yarn resourcemanager。

    背景: 接到任务,需要在一个一天数据量在460亿条记录的hive表中,筛选出某些host为特定的值时才解析该条记录的http_content中的经纬度: 解析规则譬如: 需要解析host: api.m ...

  5. 第九章伪代码编程过程 The PseudoCode Programming Process

    目录: 1.创建类和子程序的步骤概述 2.伪代码 3.通过伪代码编程过程创建子程序 4.伪代码编程过程的替代方案 一.创建类和子程序的步骤概述 (1)创建一个类的步骤 1.创建类的总体设计 2.创建类 ...

  6. android switch语句报错:case expressions must be constant expressions

    今天无意中碰见了   case expressions must be constant expressions 的问题 写了一个 switch(item.getItemId()) { case R. ...

  7. 写了placement new就要写placement delete

    "placement new"通常是专指指定了位置的new(std::size_t size, void *mem),用于vector申请capacity剩余的可用内存. 但广义的 ...

  8. Android中处理崩溃异常和记录日志

    大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...

  9. [原创]使用Gradle的插件EnIDE build的时候,输出的中文总是乱码。

    使用Gradle的插件EnIDE build的时候,输出的中文总是乱码.解决办法:在EnIDE的设置里面,设置JVM options GRADLE_OPTS 为:-Dfile.encoding=UTF ...

  10. The constructor BASE64Encoder() is not accessible due to restriction on required library

    在Eclipse中编写Java代码时,用到了BASE64Decoder,import sun.misc.BASE64Decoder;可是Eclipse提示:Access restriction : T ...