d2.js學習筆記(七)——動態SVG座標空間

目標json

  在這一章,咱們將學習如何使SVG座標空間是動態的,這樣咱們的數據可視化不論數據是什麼,都始終是可見的。數組

  咱們會使得SVG座標空間尺度上調或下調來適於咱們的數據。app

三個SVG長方形svg

  咱們就從三個長方形做爲開始:oop

 1   var jsonRectangles = [
 2     { "x_axis": 10, "y_axis": 10, "height": 20, "width":20, "color" : "green" },
 3     { "x_axis": 40, "y_axis": 40, "height": 20, "width":20, "color" : "purple" },
 4     { "x_axis": 70, "y_axis": 70, "height": 20, "width":20, "color" : "red" }];
 5
 6   var svgContainer = d3.select("body").append("svg")
 7                                    .attr("width", 100)
 8                                    .attr("height", 100);
 9
10   var rectangles = svgContainer.selectAll("rect")
11                             .data(jsonRectangles)
12                             .enter()
13                             .append("rect");
14
15   var rectangleAttributes = rectangles
16                          .attr("x", function (d) { return d.x_axis; })
17                          .attr("y", function (d) { return d.y_axis; })
18                          .attr("height", function (d) { return d.height; })
19                          .attr("width", function (d) { return d.width; })
20                          .style("fill", function(d) { return d.color; });

  獲得的結果是:學習

three rectangle

  漂亮!spa

  其中SVG容器:code

1   var svgContainer = d3.select("body").append("svg")
2                                       .attr("width", 100)
3                                       .attr("height", 100);

寬100單位,高100單位。對象

  也就是說,圖中三個長方形中最右下角的點的座標(90,90)仍然在SVG容器視窗範圍內。blog

  可是,若是紫色的長方形的x座標,忽然增長了四倍,從40變成160,結果會怎麼樣呢?

 1   //原來
 2   { "x_axis": 40, "y_axis": 40, "height": 20, "width":20, "color" : "purple" }
 3
 4   //變爲
 5   { "x_axis": 160, "y_axis": 40, "height": 20, "width":20, "color" : "purple" }
 6
 7   //所以,數據集 jsonRectangles 變成了:
 8   var jsonRectangles = [
 9   { "x_axis": 10, "y_axis": 10, "height": 20, "width":20, "color" : "green" },
10   { "x_axis": 160, "y_axis": 40, "height": 20, "width":20, "color" : "purple" },
11   { "x_axis": 70, "y_axis": 70, "height": 20, "width":20, "color" : "red" }];

  這也就是說,紫色長方形有座標值(160,40)。

  這個座標已經超出高100寬100的範圍。

  這樣咱們的數據可視化結果成了:

out of viewport

  就像咱們想象的那樣,太糟了!

動態調整SVG容器空間

  咱們真正須要的是,可以根據咱們的數據,對SVG容器的width、height屬性進行動態調節。

  咱們打算使用基礎JavaScript循環(loop)來對JSON對象數組處理,找出最大的X座標he最大的Y座標。

  最大的x座標和最大的y座標就是長方形的最右下角點的座標。

 1 //新的jsonRectangle數據(其中紫色長方形的x座標如今是160)
 2 var jsonRectangles = [
 3 {"x_axis":10,"y_axis":10,"height":20,"width":20,"color":"green"},
 4 {"x_axis":160,"y_axis":40,"height":20,"width":20,"color":"purplr"},
 5 {"x_axis":70,"y_axis":70,"height":20,"width":20,"color":"red"}
 6 ];
 7 
 8 var max_x = 0;//用於存儲最大x座標
 9 var max_y = 0;//用於存儲最大y座標
10 
11 //在jsonRectangle數組上的循環
12 for(var i = 0;i<jsonRectangles.length;i++){
13 var temp_x,temp_y;
14 
15 //爲了獲得最右的點,咱們須要把x座標和width相加
16 temp_x = jsonRectangles[i].x_axis+jsonRectangles[i].width;
17 
18 //爲了獲得最下面的點,咱們須要把y座標和height相加
19 temp_y = jsonRectangles[i].y_axis+jsonRectangles[i].height;
20 
21 /**
22 *若是臨時x座標比max_x大,
23 *那麼就讓max_x等於temp_x
24 *不然,什麼都不用作
25 *同理,max_y也同樣
26 */
27 if(temp_x>=max_x){
28   max_x = temp_x;  
29 }
30 
31 if(temp_y>=max_y){
32   max_y = temp_y;  
33 }
34 
35 }//循環中止
36 
37 max_x;
38 //返回180
39 
40 max_y;
41 //返回 90

  若是數據發生了變化,max_x和max_y將始終都是數據中的最大值。

  如今,咱們能夠更新咱們的SVG容器:

 1 //原來
 2 var svgContainer = d3.select("body").append("svg")
 3 .attr("height",200)
 4 .attr("width",200);
 5 
 6 //如今(使用變量max_x和max_y)
 7 var svgContainer = d3.select("body").append("svg")
 8 .attr("width",max_x + 20)
 9 .attr("width",max_x + 20);
10 //注意 — 在這裏給max_x和max_y各加了20,是爲了給元素多一些文本空間

  這樣,SVG容器就一直可以顯示右邊的最大尺寸,咱們的數據也就能正確的出如今其內部。

成品

  既然問題解決了,完整的代碼以下:

 1   var jsonRectangles = [
 2     { "x_axis": 10, "y_axis": 10, "height": 20, "width":20, "color" : "green" },
 3     { "x_axis": 160, "y_axis": 40, "height": 20, "width":20, "color" : "purple" },
 4     { "x_axis": 70, "y_axis": 70, "height": 20, "width":20, "color" : "red" }];
 5
 6   var max_x = 0;
 7   var max_y = 0;
 8
 9   for (var i = 0; i < jsonRectangles.length; i++) {
10     var temp_x, temp_y;
11     var temp_x = jsonRectangles[i].x_axis + jsonRectangles[i].width;
12     var temp_y = jsonRectangles[i].y_axis + jsonRectangles[i].height;
13
14     if ( temp_x >= max_x ) { max_x = temp_x; }
15
16     if ( temp_y >= max_y ) { max_y = temp_y; }
17   }
18
19   var svgContainer = d3.select("body").append("svg")
20                                    .attr("width", max_x)
21                                    .attr("height", max_y)
22
23   var rectangles = svgContainer.selectAll("rect")
24                             .data(jsonRectangles)
25                             .enter()
26                             .append("rect");
27
28   var rectangleAttributes = rectangles
29                          .attr("x", function (d) { return d.x_axis; })
30                          .attr("y", function (d) { return d.y_axis; })
31                          .attr("height", function (d) { return d.height; })
32                          .attr("width", function (d) { return d.width; })
33                          .style("fill", function(d) { return d.color; });

finished

  如今,全部的長方形都出現啦!

  SVG視窗可以把最右的(max_x+20,max_y+20)包括進去。

  並且,SVG視窗是動態生成,不須要咱們去手動的更新width和height。

  使用JavaScript的For循環,咱們就可以實現動態的resize咱們的SVG視窗容器來適應數據。

  若是數據再次改變,咱們的視窗(容器)也可以隨時包含所有的數據可視化結果。

相關文章
相關標籤/搜索