【问题标题】:Height transitions go from top down, rather than from bottom up in D3高度转换从上到下,而不是在 D3 中从下到上
【发布时间】:2016-03-21 08:21:57
【问题描述】:

我正在使用以下代码制作条形图:

svg.selectAll(".bar")
    .data(data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
        return x(d.value) - barWidth / 2;
    })
    .attr("width", barWidth)
    .attr("y", function(d) {
        return y(d.frequency);
    })
    //.attr("height", 0)
    //.transition()
    .attr("height", function(d) {
        return height - y(d.frequency);
    });

如果我添加注释掉的行,那么条形将从高度 0 过渡到它的正确高度;但是,由于某种原因,条形图不是从 x 轴向上“增长”,而是从最高值开始,然后朝 x 轴向下“增长”。为什么会这样?我该如何解决这个问题?

【问题讨论】:

    标签: javascript d3.js svg


    【解决方案1】:

    为什么会这样?

    这种设置方式意味着您将rect 的顶部设置为与d.frequency 相关的任何y 值,然后将底部定义为x 轴本身(通过从最大高度中减去计算出的 y 值)。鉴于在转换之前您有效地修复了 y 值,然后获得转换的高度,您实际上所做的只是移动 rect 的底部,从而产生您描述的效果。

    我该如何解决这个问题?

    最简单的解决方法是同时转换 y 值和高度,以保持rect 底部固定的方式。为此,在转换之前只需将y attr 设置为y(0),然后transition() 之后,将y attr 设置为计算版本,即y(d.frequency) .像这样:

    svg.selectAll(".bar")
        .data(data)
        .enter().append("rect")
        .attr("class", "bar")
        .attr("x", function(d) {
            return x(d.value) - barWidth / 2;
        })
        .attr("width", barWidth)
        .attr("y", function(d) {
            return y(0);
        })
        .attr("height", 0)
        .transition()
        .attr("y", function(d) {
            return y(d.frequency);
        })
        .attr("height", function(d) {
            return height - y(d.frequency);
        });
    

    【讨论】:

      【解决方案2】:

      如果您检查 bar 元素,您可以看到 d3 条从所需的height 绘制到y 位置。所以你应该尝试如下所示。

      svg.selectAll(".bar")
        .data(data)
        .enter().append("rect")
        .attr("class", "bar")
        .attr("x", function(d) {
          return x(d.letter);
        })
        .attr("width", x.rangeBand())
        .attr("height", function(d) {
          return height - y(d.frequency);
        })
        .attr("y", height)
        .transition()
        .duration(500)
        .attr("y", function(d) {
          return y(d.frequency);
        });
      

      工作 sn-p:

      var margin = {
          top: 20,
          right: 20,
          bottom: 30,
          left: 40
        },
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;
      
      var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);
      
      var y = d3.scale.linear()
        .range([height, 0]);
      
      var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");
      
      var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(10, "%");
      
      var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
      
      var data = [{
        "letter": "A",
        "frequency": 0.08167
      }, {
        "letter": "B",
        "frequency": 0.01492
      }, {
        "letter": "C",
        "frequency": 0.02782
      }, {
        "letter": "D",
        "frequency": 0.04253
      }, {
        "letter": "E",
        "frequency": 0.12702
      }, {
        "letter": "F",
        "frequency": 0.02288
      }, {
        "letter": "G",
        "frequency": 0.02015
      }, {
        "letter": "H",
        "frequency": 0.06094
      }, {
        "letter": "I",
        "frequency": 0.06966
      }, {
        "letter": "J",
        "frequency": 0.00153
      }, {
        "letter": "K",
        "frequency": 0.00772
      }, {
        "letter": "L",
        "frequency": 0.04025
      }, {
        "letter": "M",
        "frequency": 0.02406
      }, {
        "letter": "N",
        "frequency": 0.06749
      }, {
        "letter": "O",
        "frequency": 0.07507
      }, {
        "letter": "P",
        "frequency": 0.01929
      }, {
        "letter": "Q",
        "frequency": 0.00095
      }, {
        "letter": "R",
        "frequency": 0.05987
      }, {
        "letter": "S",
        "frequency": 0.06327
      }, {
        "letter": "T",
        "frequency": 0.09056
      }, {
        "letter": "U",
        "frequency": 0.02758
      }, {
        "letter": "V",
        "frequency": 0.00978
      }, {
        "letter": "W",
        "frequency": 0.0236
      }, {
        "letter": "X",
        "frequency": 0.0015
      }, {
        "letter": "Y",
        "frequency": 0.01974
      }, {
        "letter": "Z",
        "frequency": 0.00074
      }, {
        "letter": "LICENSE",
        "frequency": 0
      }];
      
      
      x.domain(data.map(function(d) {
        return d.letter;
      }));
      y.domain([0, d3.max(data, function(d) {
        return d.frequency;
      })]);
      
      svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);
      
      svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .text("Frequency");
      
      svg.selectAll(".bar")
        .data(data)
        .enter().append("rect")
        .attr("class", "bar")
        .attr("x", function(d) {
          return x(d.letter);
        })
        .attr("width", x.rangeBand())
        .attr("height", function(d) {
          return height - y(d.frequency);
        })
        .attr("y", height)
        .transition()
        .duration(500)
        .attr("y", function(d) {
          return y(d.frequency);
        });
      
      
      function type(d) {
        d.frequency = +d.frequency;
        return d;
      }
      .bar {
        fill: steelblue;
      }
      .bar:hover {
        fill: brown;
      }
      .axis {
        font: 10px sans-serif;
      }
      .axis path,
      .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
      }
      .x.axis path {
        display: none;
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

      【讨论】:

        【解决方案3】:

        一个反直觉的东西让我创建了一些颠倒的图表是 svg 坐标 x,y 从左上角的 0,0 开始,而不是左下角。

        【讨论】:

          【解决方案4】:

          我认为属性("class", bar) 不是必需的,您可以使用 rangeBand() 来计算宽度并检查您的 Yaxis 比例取值 [height,0] 并且其余代码看起来不错。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-12
            • 1970-01-01
            • 2013-02-27
            • 2013-03-12
            • 2012-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-26
            相关资源
            最近更新 更多