1. 程式人生 > >資料視覺化-中國地圖的製作(地圖的省級聯動)

資料視覺化-中國地圖的製作(地圖的省級聯動)

在資料視覺化中,地圖是很重要的一部分。很多情況會與地圖有關聯,如中國各省的人口多少,GDP多少等,都可以和地圖聯絡在一起。

一.地圖資料的獲取

2.聯絡博主,會給您共享一份地圖的JSON資料。

二.地圖的製作

第一步:定義畫板,並將畫板新增到body中

var width  = 1000;
var height = 1000;
var svg = d3.select("body")
	    .append("svg")
	    .attr("width", width)
            .attr("height", height)
	    .attr("transform", "translate(0,0)");

第二步:定義一個投影函式來轉換經緯度。因為,地球上的經度和緯度的資訊,都是三維的,而要在網頁上顯示的是二維的,所以要設定一個投影函式來轉換經緯度,本文使用d3.geo.mercator()的投影方式。各種投影函式,可以參考: https://github.com/mbostock/d3/wiki/Geo-Projections

var projection = d3.geo.mercator()
		       .center([107, 31])
		       .scale(550)
    		       .translate([width/2, height/2]);

第 2 行:center() 設定地圖的中心位置,[107,31] 指的是經度和緯度。

第 3 行:scale() 設定放大的比例。數值越大,地圖被放大的比例越大。將數值寫在括號中即可。

第 4 行:translate(x,y) 設定平移。第一個引數x為沿x軸移動的距離,第二個引數y為沿y軸移動的距離。

第三步:使用第二步定義出來的投影函式生成路徑。projection() 是設定生成器的投影函式,把上面定義的投影傳入即可。以後,當使用此生成器計算路徑時,會自己加入投影的影響。

var path = d3.geo.path()
		 .projection(projection);

第四步:向伺服器請求檔案並繪製地圖

d3.json("china.geojson", function(error, root) {
		if (error)  return console.error(error);
                svg.selectAll("path")
			.data(root.china.features)
			.enter()
			.append("path")
			.attr("stroke","#000")
			.attr("stroke-width",1)
			.attr("fill", function(d,i){
				return color;
			})
			.attr("fill", "rgba(6,85,178,0.5)")
			.attr("d", path)
			.on("mouseover",function(d,i){
                                d3.select(this)
                                  .attr("fill","yellow");
                        })
                        .on("mouseout",function(d,i){
                               d3.select(this)
                                 .attr("fill","rgba(6,85,178,0.5)");
                        })
                })

結果如圖:


再次宣告:d3.json() 不能直接讀取本地檔案,因此你需要搭建一個伺服器,例如 Apache。

三.給地圖上新增省份的名稱

  svg.selectAll("text")
            .data(root.china.features)
            .enter().append("svg:text")
            .text(function (d, i) {
                return d.properties.name
            })           .attr("fill", "rgba(6,85,178,0.5)")
 
            .attr("x", function (d) {
                var local = projection([d.properties.cp[0], d.properties.cp[1]])
                return local[0]
            })
            .attr("y", function (d) {
                var local = projection([d.properties.cp[0], d.properties.cp[1]])
                return local[1]
            })
            .attr("fill", "#04adff")
            .style("font-size", "10px")

注:地圖的JSON資料中需要有省份的中心點座標。結果如下:


四.實現地圖的省級聯動(即點選某省時出現某個省份的地圖)

第一步:給每個省份的路徑新增一個屬性,屬性值為對應的省份名。以便點選時,進行判斷,是哪個省份被點選,以及需要調取哪個省份的地圖資料。

svg.selectAll("path")
        .attr("tag", function(d){
             return d.properties["name"];
    	})

第二步:新增點選事件

svg.selectAll("path")
   .on("click",function(e){
       if(this.getAttribute('tag')=="黑龍江"){
           d3.json("china.geojson", function(error, root) { //請求黑龍江地區的資料
	       if (error) return console.error(error);
	       svg.selectAll("*").remove(); //清空畫板
	           svg.selectAll("path")
		      .data(root.黑龍江.features)
		      .enter()
		      .append("path")
		      .attr("stroke","#000")
		      .attr("stroke-width",1)
		      .attr("fill", "rgba(6,85,178,0.5)")
		      .attr("d", path)
		      .on("mouseover",function(d,i){
		            d3.select(this)
			      .attr("fill","yellow");
		      })
	              .on("mouseout",function(d,i){
			   d3.select(this)
		             .attr("fill","rgba(6,85,178,0.5)");
		      })
				            
	   })
       }   })

五.實現地圖上不同區域有不同的著色(如圖)

會用到d3中的過濾器,判斷資料當中各省份的經緯度,根據經緯度的範圍進行著色,具體程式碼如下:

d3.selectAll("path").filter(function(d,i){
    if(d.properties.id>=31&&d.properties.id<=35&&d.properties.id!=34){
        d3.select(this).attr("fill", function(d,i){
	    return "#03aefe";
	})
    }
})