3.使用分类范围尺
在某些情况下,我们可能需要将我们的数据映射到一些分类的(顺序的)值,比如[a,b,c]或者[# 1f77b4, # ff7f0e, #2ca02c]等,如何用D3来处理这类映射呢,本节将回答这个问题。
老规矩还是先上代码,打开你的编辑器,输入如下代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Ordinal Scale</title> <link rel="stylesheet" type="text/css" href="styles.css"/> <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> </head> <body> <div id="alphabet" class="clear"> <span>Ordinal Scale with Alphabet<br></span> <span>Mapping [1..10] to ["a".."j"]<br></span> </div> <div id="category10" class="clear"> <span>Ordinal Color Scale Category 10<br></span> <span>Mapping [1..10] to category 10 colors<br></span> </div> <div id="category20" class="clear"> <span>Ordinal Color Scale Category 20<br></span> <span>Mapping [1..10] to category 20 colors<br></span> </div> <div id="category20b" class="clear"> <span>Ordinal Color Scale Category 20b<br></span> <span>Mapping [1..10] to category 20b colors<br></span> </div> <div id="category20c" class="clear"> <span>Ordinal Color Scale Category 20c<br></span> <span>Mapping [1..10] to category 20c colors<br></span> </div> <script type="text/javascript"> var max = 10, data = []; for (var i = 0; i < max; ++i) data.push(i); // <-A var alphabet = d3.scale.ordinal() // <-B .domain(data) .range(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]); function render(data, scale, selector) { // <-C d3.select(selector).selectAll("div.cell") .data(data) .enter().append("div").classed("cell", true); d3.select(selector).selectAll("div.cell") .data(data) .exit().remove(); d3.select(selector).selectAll("div.cell") .data(data) .style("display", "inline-block") .style("background-color", function(d){ // <-D return scale(d).indexOf("#")>=0?scale(d):"white"; }) .text(function (d) { // <-E return scale(d); }); } render(data, alphabet, "#alphabet"); // <-F render(data, d3.scale.category10(), "#category10"); render(data, d3.scale.category20(), "#category20"); render(data, d3.scale.category20b(), "#category20b"); render(data, d3.scale.category20c(), "#category20c"); // <-G </script> </body> </html>
运行该代码我们将看到下图的结果:
这种类型的映射在数据可视化中非常常见,比如你可能想要将特定的数据点映射成对应的字符串或者是RGB代码,这样你就可以应用到CSS样式中。D3提供了专业的范围尺函数来完成这项工作,下面我们就来详细看看上面例子的代码。
在上面的例子中代码A处定义了一个简单的从0到9的数组。
var max = 10, data = [];
for (var i = 0; i < max; ++i) data.push(i); // <-A
接着在B行调用d3.scale.ordinal()方法,创建了一个分类范围尺,然后将其定义域设置为我们在A处创建的数组即0-9的数字,将值域设置成字母表中的a-j。当范围尺定义后,我们可以调用scale函数来完成数字到字母的映射,比如调用alphabet(0)将得到a,alphabet(4)将得到e。等等。
在C处,render函数被定义用来创建分别代表了数组中数字的10个div元素到页面中。每个div元素的背景色被设置成scale函数的返回值或者是白色如果返回值不是RGB代码。
function render(data, scale, selector) { // <-C
d3.select(selector).selectAll("div.cell")
.data(data)
.enter().append("div").classed("cell", true);
d3.select(selector).selectAll("div.cell")
.data(data)
.exit().remove();
d3.select(selector).selectAll("div.cell")
.data(data)
.style("display", "inline-block")
.style("background-color", function(d){ // <-D
return scale(d).indexOf("#")>=0?scale(d):"white";
在E处,我们将scale函数的返回值赋值给每个div的text,将其现实在页面中。
.text(function (d) { // <-E
return scale(d);
});
现在所有的框架我们都搭建完毕,从F到G行,render函数被多次调用,并且使用不同的分类范围尺来产生不同的输出效果,在F行我们是使用字母表的映射,后面分别使用了D3内建的不同的颜色范围尺,因为给不同元素分配不同的颜色是可视化常用到的,比如饼图、表格等,所以d3为我们准备了很多不同的颜色范围尺,比如本例中的几个,你同样也可以自己通过将分类范围尺的值域设置成你想要的颜色来定义自己的颜色范围尺,比如:
d3. scale.ordinal() .range([# 1f77b4, # ff7f0e, # 2ca02c]