比例尺是 D3 中很重要的一个概念,直接用数值的大小来表明像素不是一种好方法数组
1、为何须要比例尺app
制做一个柱形图,会有一个数组:var dataset = [ 250 , 210 , 170 , 130 , 90 ];dom
绘图时,直接使用 250 给矩形的宽度赋值,即矩形的宽度就是 250 个像素。此方式很是具备局限性,若是数值过大或太小,例如:svg
var dataset_1 = [ 2.5 , 2.1 , 1.7 , 1.3 , 0.9 ];
var dataset_2 = [ 2500, 2100, 1700, 1300, 900 ];函数
对以上两个数组,毫不可能用 2.5 个像素来表明矩形的宽度,那样根本看不见;也不可能用 2500 个像素来表明矩形的宽度,由于画布没有那么长。spa
因而,咱们须要一种计算关系,可以:将某一区域的值映射到另外一区域,其大小关系不变。这就是比例尺(Scale)。code
2、有哪些比例尺blog
比例尺,很像数学中的函数。例如,对于一个一元二次函数,有 x 和 y 两个未知数,当 x 的值肯定时,y 的值也就肯定了。ip
在数学中,x 的范围被称为定义域,y 的范围被称为值域。utf-8
D3 中的比例尺,也有定义域和值域,分别被称为 domain 和 range。开发者须要指定 domain 和 range 的范围,如此便可获得一个计算关系。
D3 提供了多种比例尺,下面介绍最经常使用的两种。
一、线性比例尺
线性比例尺,能将一个连续的区间,映射到另外一区间。要解决柱形图宽度的问题,就须要线性比例尺。假设有如下数组:var dataset = [1.2, 2.3, 0.9, 1.5, 3.3];
现有要求以下:
将 dataset 中最小的值,映射成 0;将最大的值,映射成 300。
var min = d3.min(dataset); var max = d3.max(dataset); var linear = d3.scale.linear() .domain([min, max]) .range([0, 300]); linear(0.9); //返回 0 linear(2.3); //返回 175 linear(3.3); //返回 300
其中,d3.scale.linear() 返回一个线性比例尺。domain() 和 range() 分别设定比例尺的定义域和值域。在这里还用到了两个函数,它们常常与比例尺一块儿出现:
这两个函数可以求数组的最大值和最小值,是 D3 提供的。按照以上代码,
比例尺的定义域 domain 为:[0.9, 3.3]
比例尺的值域 range 为:[0, 300]
所以,当输入 0.9 时,返回 0;当输入 3.3 时,返回 300。当输入 2.3 时呢?返回 175,这是按照线性函数的规则计算的。
有一点请你们记住:
d3.scale.linear() 的返回值,是能够当作函数来使用的。所以,才有这样的用法:linear(0.9)。
二、序数比例尺
有时候,定义域和值域不必定是连续的。例如,有两个数组:
var index = [0, 1, 2, 3, 4];
var color = ["red", "blue", "green", "yellow", "black"];
咱们但愿 0 对应颜色 red,1 对应 blue,依次类推。
可是,这些值都是离散的,线性比例尺不适合,须要用到序数比例尺。
var ordinal = d3.scale.ordinal() .domain(index) .range(color); ordinal(0); //返回 red ordinal(2); //返回 green ordinal(4); //返回 black
3、给柱形图添加比例尺
<body> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script> var width = 300; //画布的宽度 var height = 300; //画布的高度 var svg = d3.select("body") //选择文档中的body元素 .append("svg") //添加一个svg元素 .attr("width", width) //设定宽度 .attr("height", height); //设定高度 var dataset = [ 2.5 , 2.1 , 1.7 , 1.3 , 0.9 ]; var linear = d3.scale.linear() .domain([0, d3.max(dataset)]) .range([0, 250]); var rectHeight = 25; //每一个矩形所占的像素高度(包括空白) svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("x",20) .attr("y",function(d,i){ return i * rectHeight; }) .attr("width",function(d){ return linear(d);//在这里用比例尺 }) .attr("height",rectHeight-2) .attr("fill","steelblue"); </script> </body>