目標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; });
獲得的結果是:學習
漂亮!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的範圍。
這樣咱們的數據可視化結果成了:
就像咱們想象的那樣,太糟了!
動態調整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; });
如今,全部的長方形都出現啦!
SVG視窗可以把最右的(max_x+20,max_y+20)包括進去。
並且,SVG視窗是動態生成,不須要咱們去手動的更新width和height。
使用JavaScript的For循環,咱們就可以實現動態的resize咱們的SVG視窗容器來適應數據。
若是數據再次改變,咱們的視窗(容器)也可以隨時包含所有的數據可視化結果。