在【入门 - 第 10 章】作了一张中国地图,其中各省份的颜色值都是随意赋值的。如果要将一些值反映在地图上,可以利用颜色的变化来表示值的变化。

1. 思路

例如,有值域的范围为:

[10, 500]

现希望10用浅绿表示,500用深绿表示,10到500之间的值用浅绿和深绿之间的颜色表示。显然,此处需要一个函数,传入的参数是10到500之间的值,返回值是浅绿到深绿之间的颜色值。

高级 - 第 5.1 章】介绍的颜色插值函数正好可以派上用场。

var palegreen = d3.rgb(66,251,75);	//浅绿
var darkgreen = d3.rgb(2,100,7); //深绿 var color = d3.interpolate(a,b); //颜色插值函数

这段代码最后得到的color可作为函数使用,参数的范围为[0, 1],当参数为0时,返回浅绿,当参数为1时,返回深绿。但是,现在的值域是[10, 500],范围不是[0, 1]。因此,先定义一个线性比例尺,将[10, 500]按线性关系映射到[0, 1]。

var linear = d3.scale.linear()
.domain([10, 500])
.range([0, 1]);

如此一来,便可结合比例尺来使用颜色插值函数。

color( linear(10) );		//返回浅绿RGB(66,251,75)
color( linear(250) ); //返回浅绿和深绿之间的值
color( linear(500) ); //返回深绿RGB(2,100,7)

2. 绘制完整的中国地图

在【入门 - 第 10 章】有绘制中国地图的方法。

本例中更改为读取 TopoJSON 文件,这种类型的文件更小,能提高读取速度。关于 TopoJSON 和 GeoJSON 的区别,请参见【入门 - 第 10.3 章】。

要使用 TopoJSON 的相关函数,需要引用:

<script src="http://d3js.org/topojson.v1.min.js" charset="utf-8"></script>

读取之后,使用 topojson.feature 将其转换为 GeoJSON 文件,不错,最终使用时还是 GeoJSON 的格式,但是在读取时速度会快很多。

d3.json("china.topojson", function(error, toporoot) {
if (error)
return console.error(error); //输出china.topojson的对象
console.log(toporoot); //将TopoJSON对象转换成GeoJSON,保存在georoot中
var georoot = topojson.feature(toporoot,toporoot.objects.china); //输出GeoJSON对象
console.log(georoot); //包含中国各省路径的分组元素
var china = svg.append("g"); //添加中国各种的路径元素
var provinces = china.selectAll("path")
.data( georoot.features )
.enter()
.append("path")
.attr("class","province")
.style("fill", "#ccc")
.attr("d", path ); });

此外,南海诸岛的地图是不包含在地图文件里的。但是,中国的南海诸岛,一般只是显示在右下角,用一个方框框起来而已,不一定要做成GeoJSON格式。直接制作一个SVG格式的文件即可。

我制作了一个:southchinasea.svg

添加到代码里,形如:

d3.xml("southchinasea.svg", function(error, xmlDocument) {
svg.html(function(d){
return d3.select(this).html() + xmlDocument.getElementsByTagName("g")[0].outerHTML;
}); var gSouthSea = d3.select("#southsea"); gSouthSea.attr("transform","translate(540,410)scale(0.5)")
.attr("class","southsea"); });

3. 为各省市添加颜色

假设现在有一组反应各省旅游业发展的数据,保存到文件 tourism.json 里:

{
"name": "中国",
"provinces":
[
{"name": "北京", "value": 14149 },
{"name": "天津", "value": 2226.41},
{"name": "河北", "value": 1544.94},
{"name": "山西", "value": 3720.24},
// 省略
]
}

读取此文件后,按照第一节的思路,创建一个颜色插值函数:

                //求最大值和最小值
var maxvalue = d3.max(valuedata.provinces, function(d){ return d.value; });
var minvalue = 0; //定义一个线性比例尺,将最小值和最大值之间的值映射到[0, 1]
var linear = d3.scale.linear()
.domain([minvalue, maxvalue])
.range([0, 1]); //定义最小值和最大值对应的颜色
var a = d3.rgb(0,255,255); //浅蓝色
var b = d3.rgb(0,0,255); //蓝色 //颜色插值函数
var computeColor = d3.interpolate(a,b);

computeColor 是我们需要的函数。接下来,只需要修改各省份的填充色即可,为了方便,将读取到的数据都放到一个values数组里,令其索引号为各省的名称。

		//将读取到的数据存到数组values,令其索引号为各省的名称
var values = [];
for(var i=0; i<valuedata.provinces.length; i++){
var name = valuedata.provinces[i].name;
var value = valuedata.provinces[i].value;
values[name] = value;
} //设定各省份的填充色
provinces.style("fill", function(d,i){
var t = linear( values[d.properties.name] );
var color = computeColor(t);
return color.toString();
});

这样,虽然把地图绘制了,填充色也按照值域对应了,但是还需要一个标志,来告诉用户什么颜色对应什么值。

4. 添加颜色标志

高级 - 第 5.1 章】有提到如何将渐变的颜色填充到一个矩形上,在这里就用此法制作一个颜色标志。

		//定义一个线性渐变
var defs = svg.append("defs"); var linearGradient = defs.append("linearGradient")
.attr("id","linearColor")
.attr("x1","0%")
.attr("y1","0%")
.attr("x2","100%")
.attr("y2","0%"); var stop1 = linearGradient.append("stop")
.attr("offset","0%")
.style("stop-color",a.toString()); var stop2 = linearGradient.append("stop")
.attr("offset","100%")
.style("stop-color",b.toString()); //添加一个矩形,并应用线性渐变
var colorRect = svg.append("rect")
.attr("x", 20)
.attr("y", 490)
.attr("width", 140)
.attr("height", 30)
.style("fill","url(#" + linearGradient.attr("id") + ")"); //添加文字
var minValueText = svg.append("text")
.attr("class","valueText")
.attr("x", 20)
.attr("y", 490)
.attr("dy", "-0.3em")
.text(function(){
return minvalue;
}); var maxValueText = svg.append("text")
.attr("class","valueText")
.attr("x", 160)
.attr("y", 490)
.attr("dy", "-0.3em")
.text(function(){
return maxvalue;
});

5. 结果

结果如下如所示,

完整代码打开以下链接,右键选择查看源代码:

http://www.ourd3js.com/demo/G-6.0/range.html

谢谢阅读。

文档信息

【 D3.js 高级系列 — 6.0 】 值域和颜色的更多相关文章

  1. 【 D3.js 高级系列 — 4.0 】 矩阵树图

    矩阵树图(Treemap),也是层级布局的扩展,根据数据将区域划分为矩形的集合.矩形的大小和颜色,都是数据的反映.许多门户网站都能见到类似图1,将照片以不同大小的矩形排列的情形,这正是矩阵树图的应用. ...

  2. 【 D3.js 高级系列 — 1.0 】 文本的换行

    在 SVG 中添加文本是使用 text 元素.但是,这个元素不能够自动换行,超出的部分就显示不出来了,怎么办呢? 高级系列开篇前言 从今天开始写高级系列教程.还是那句话,由于本人实力有限,不一定保证入 ...

  3. 【 D3.js 高级系列 — 3.0 】 堆栈图

    堆栈图布局(Stack Layout)能够计算二维数组每一数据层的基线,以方便将各数据层叠加起来.本文讲解堆栈图的制作方法. 先说说什么是堆栈图. 例如,有如下情况: 某公司,销售三种产品:个人电脑. ...

  4. 【 D3.js 高级系列 — 2.0 】 机械图 + 人物关系图

    机械图(力路线图)结合老百姓的关系图中的生活,这是更有趣. 本文将以此为证据,所列的如何图插入外部的图像和文字的力学. 在[第 9.2 章]中制作了一个最简单的力学图.其后有非常多朋友有疑问,基本的问 ...

  5. 【 D3.js 高级系列 — 10.0 】 思维导图

    思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩展来的,其中的树状图(tree layout)和集群图(cluster layou ...

  6. 【 D3.js 高级系列 — 9.0 】 交互式提示框

    一般来说,图表中不宜存在过多文字.但是,有时需要一些文字来描述某些图形元素.那么,可以实现一种交互:当用户鼠标滑到某图形元素时,出现一个提示框,里面写有描述文字.这是一种简单.普遍的交互式,几乎适用于 ...

  7. 【 D3.js 高级系列 — 8.0 】 标线

    有时候,需要在地图上绘制连线,表示"从某处到某处"的意思,这种时候在地图上绘制的连线,称为"标线". 1. 标线是什么 标线,是指地图上需要两个坐标以上才能表示 ...

  8. 【 D3.js 高级系列 — 7.0 】 标注地点

    有时需要告诉用户地图上的一些目标,如果该目标是只需要一个坐标就能表示的,称其为"标注". 1. 标注是什么 标注,是指地图上只需要一个坐标即可表示的元素.例如,在经纬度(116, ...

  9. 【 D3.js 高级系列 — 5.0 】 颜色

    颜色是作图不可少的概念,常用的标准有 RGB 和 HSL,D3 提供了创建颜色对象的方法,能够相互转换和插值. RGB色彩模式是通过对红(Red).绿(Green).蓝(Blue)三个颜色通道相互叠加 ...

随机推荐

  1. nenu contest3

    http://vjudge.net/contest/view.action?cid=55702#overview 12656 - Almost Palindrome http://uva.online ...

  2. web系统之session劫持解决

    session劫持是一种比较复杂的攻击方法.大部分互联网上的电脑多存在被攻击的危险.这是一种劫持tcp协议的方法,所以几乎所有的局域网,都存在被劫持 可能. 两台主机要想进行TCP通信,必须经过一个三 ...

  3. How do you design object oriented projects?

    what are things you do during the high level design phase (before you begin programming) to determin ...

  4. HDU 1546 Idiomatic Phrases Game(最短路,Dijsktra,理解题意很重要)

    题目 1.注意因为要判断能不能到达,所以要在模版里面判断k有没有更新. 2.看懂题目意思和案例的解法很重要. #define _CRT_SECURE_NO_WARNINGS //题目大意:现要进行单词 ...

  5. cf div2 234 E

    E. Inna and Binary Logic time limit per test 3 seconds memory limit per test 256 megabytes input sta ...

  6. Javascript 电子时钟源码

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  7. 将DJANGO管理界面的filter_horizontal移到前面来复用

    参考URL: http://www.hoboes.com/Mimsy/hacks/replicating-djangos-admin/reusing-djangos-filter_horizontal ...

  8. Android ImageButton的背景(图片)大小

    使用ImageButton的background属性,而不用src属性. 然后使用width和height进行调整.

  9. 1829 A Bug's Life

    A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  10. Windows JDK环境变量的配置

    下载JDK:http://www.oracle.com/technetwork/java/javase/downloads/index.html 安装 计算机-->属性-->高级系统设置- ...