SVG和d3:在数据坐标中绘制原始矩形?

时间:2017-07-16 20:44:11

标签: javascript d3.js svg

我正在尝试学习d3来构建可视化;作为这个项目的一部分,我发现我需要绘制一些填充的矩形。这在SVG坐标中应该是直截了当的,但我想绘制数据坐标。我无法弄清楚为什么任何矩形会被画在画布之外,但这就是我在这里的最小(非)工作示例中所观察到的:https://bl.ocks.org/emprice/faed364cb1bc4cc1b0dcf8a5a2d50dac

粉红色矩形实际上超出了SVG元素的边界,如果我正确设置了x和y映射,这没有意义。是否有绘制数据坐标的技巧,我没有使用过,或者我是否错误地配置了刻度?我试过改变y比例参数(范围和域)但没有成功;以相同方式设置的x刻度似乎按预期工作。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

请记住,svg坐标从顶部开始,高度向下延伸矩形。如果你替换这一行:

 .attr("y", function(d) { return y(d.y0); })

 .attr("y", function(d) { return height- y(d.y0); })

你会得到一些看起来更合适的东西。

例如,y坐标为y1:2且y0:0的矩形。此矩形用于填充svg的整个高度。使用你的比例:

 var y = d3.scaleLinear().rangeRound([height, 0]).domain([0., 2.]);

和你的y位置:

  .attr("y", function(d) { return y(d.y0); })

您将把这个矩形的顶部放在svg的底部。对于输入y值为0,比例将返回等于height的值。使用svg y坐标height放置的任何内容都位于svg的底部。

矩形的高度也将等于height,因此矩形将从svg向下延伸(矩形的一部分将因为使用代码的边距而可见)。

相反,此矩形应显示在顶部,并一直向下延伸,为此,从height中减去缩放值,矩形将显示在svg的顶部。< / p>

如果您希望屏幕底部显示输入y值为零,而不是顶部(更典型的笛卡尔设置的抛弃SVG约定),那么您需要根据比例更改一点:< / p>

 var y = d3.scaleLinear().rangeRound([0, height]).domain([0., 2.]);

和身高:

 .attr("height", function(d) { return y(d.y1) - y(d.y0); })

并更改它,以便将顶部坐标放在rect的顶部:

.attr("y", function(d) { return y(d.y1); })

答案 1 :(得分:1)

在这个答案中,我不会解决other answer中涵盖的坐标问题,但我会给你两个重要的建议:

  1. 不要混用jQuery和D3 :不仅这不必要,而且有时也会破坏它。只是摆脱那个jQuery代码。
  2. 不要使用循环绑定数据:使用D3惯用数据绑定。
  3. 关于第2点,由于你的数据是一个对象而且data方法不接受一个对象,我们把它变成一个数组......

    var dataArray = [];
    
    for (var key in data) {
        dataArray.push({
            category: key,
            y1: data[key][0].y1,
            y0: data[key][0].y0,
            x1: data[key][0].x1,
            x0: data[key][0].x0,
        })
    }
    

    ...我们可以用来惯用绑定数据:

    g.selectAll(null)
        .data(dataArray)
        .enter()
        .append("rect")
    

    以下是包含这些更改的代码:

    <script src="https://d3js.org/d3.v4.min.js">
    </script>
    <script type="text/javascript">
      var data = {
        "cat1": [{
          "y1": 1.581699235490658,
          "y0": 0.8124126240209036,
          "x0": 0.0003786444528587656,
          "x1": 0.23513820522529344
        }],
        "cat2": [{
          "y1": 1.438932516124979,
          "y0": 0.7292493003174502,
          "x0": 0.0003786444528587656,
          "x1": 0.3029155622870125
        }, {
          "y1": 0.816326356719349,
          "y0": 0.7577181178689592,
          "x0": 0.471790988262022,
          "x1": 1.0
        }],
        "cat3": [{
          "y1": 1.04308128481062,
          "y0": 0.5216497481615152,
          "x0": 0.0,
          "x1": 0.3029155622870125
        }, {
          "y1": 1.2796737272400311,
          "y0": 0.5443780228140943,
          "x0": 0.471790988262022,
          "x1": 1.0
        }],
        "cat4": [{
          "y1": 0.8577183187799378,
          "y0": 0.5507803277857598,
          "x0": 0.44377129875047333,
          "x1": 0.4714123438091632
        }],
        "cat5": [{
          "y1": 1.411106314679798,
          "y0": 0.6447611230842676,
          "x0": 0.3032942067398713,
          "x1": 0.4714123438091632
        }],
        "cat6": [{
          "y1": 0.9875866563383724,
          "y0": 0.5832528539336078,
          "x0": 0.2355168496781522,
          "x1": 1.0
        }],
        "cat7": [{
          "y1": 1.2362146708036688,
          "y0": 0.2743087520017313,
          "x0": 0.3032942067398713,
          "x1": 0.44339265429761454
        }]
      };
    
      var dataArray = [];
    
      for (var key in data) {
        dataArray.push({
          category: key,
          y1: data[key][0].y1,
          y0: data[key][0].y0,
          x1: data[key][0].x1,
          x0: data[key][0].x0,
        })
      }
    
      // define the dimensions of the graph pane
      var margin = {
        top: 30,
        right: 30,
        bottom: 30,
        left: 30
      };
      var width = 400 - margin.left - margin.right;
      var height = 200 - margin.top - margin.bottom;
    
      // define the scale 
      var x = d3.scaleLinear().rangeRound([0, width]).domain([0., 1.]);
      var y = d3.scaleLinear().rangeRound([0, height]).domain([0., 2.]);
      var z = d3.scaleOrdinal(d3.schemeCategory10);
    
      var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom);
      var g = svg.append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
      g.selectAll(null).data(dataArray).enter()
        .append("rect")
        .attr("x", function(d) {
          return x(d.x0);
        })
        .attr("y", function(d) {
          return y(d.y0);
        })
        .attr("width", function(d) {
          return x(d.x1) - x(d.x0);
        })
        .attr("height", function(d) {
          return y(d.y1) - y(d.y0);
        })
        .attr("fill", function(d) {
          return z(d.category);
        });
    
    </script>