在【入門 - 第 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
謝謝閱讀。
文檔信息
- 版權聲明:署名(BY)-非商業性(NC)-禁止演繹(ND)
- 發表日期:2015 年 5 月 20 日
- 更多內容:OUR D3.JS - 數據可視化專題站 和 CSDN個人博客
- 備註:本文發表於 OUR D3.JS ,轉載請註明出處,謝謝