• d2.js学习笔记(七)——动态SVG坐标空间


    目标

      在这一章,我们将学习如何使SVG坐标空间是动态的,这样我们的数据可视化不论数据是什么,都始终是可见的。

      我们会使得SVG坐标空间尺度上调或下调来适于我们的数据。

    三个SVG长方形

      我们就从三个长方形作为开始:

     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

      漂亮!

      其中SVG容器:

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

    宽100单位,高100单位。

      也就是说,图中三个长方形中最右下角的点的坐标(90,90)仍然在SVG容器视窗范围内。

      但是,如果紫色的长方形的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视窗容器来适应数据。

      如果数据再次改变,我们的视窗(容器)也能够随时包含全部的数据可视化结果。

  • 相关阅读:
    【算法】CDQ分治 -- 三维偏序 & 动态逆序对
    【题解】ZJOI2007报表统计
    【乱七八糟】兰陵王
    【题解】NOI2017游戏
    【题解】JSOI2010满汉全席
    【题解】NOI2014动物园
    【题解】HNOI2010合唱队
    【题解】SDOI2010地精部落
    cf 843 D Dynamic Shortest Path [最短路+bfs]
    cf 843 B Interactive LowerBound [随机化]
  • 原文地址:https://www.cnblogs.com/winleisure/p/3522305.html
Copyright © 2020-2023  润新知