动态更改每个条形的高度 & 反转 SVG 元素

796 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的19天,点击查看活动详情

动态更改每个条形的高度

介绍

和动态设置 x 值一样,也可以把每个条形的高度设置成数组中数据点的值。

selection.attr("property", (d, i) => {

})

d 是数据点值,i 是数组中数据点的索引。

实操

改变 height 属性的回调函数,让它返回数据值乘以 3 的值。

注意: 记住,把所有数据点乘以相同的常数来对数据进行缩放(就像放大), 这有利于看清例子中条形数值之间的差异。

  1. 第一个 rect 的 height 应为 36。
  2. 第二个 rect 的 height 应为 93。
  3. 第三个 rect 的 height 应为 66。
  4. 第四个 rect 的 height 应为 51。
  5. 第五个 rect 的 height 应为 75。
  6. 第六个 rect 的 height 应为 54。
  7. 第七个 rect 的 height 应为 87。
  8. 第八个 rect 的 height 应为 42。
  9. 第九个 rect 的 height 应为 27。
<body>
  <script>
    const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];

    const w = 500;
    const h = 100;

    const svg = d3.select("body")
                  .append("svg")
                  .attr("width", w)
                  .attr("height", h);

    svg.selectAll("rect")
       .data(dataset)
       .enter()
       .append("rect")
       .attr("x", (d, i) => i * 30)
       .attr("y", 0)
       .attr("width", 25)
       .attr("height", (d, i) => {
 
          return d*3

       });
  </script>
</body>

反转 SVG 元素

介绍

你可能已经注意到了常见的条形图像是把这个翻转或者颠倒过来。 这是因为 SVG 的 (x, y) 坐标有些特别。

在 SVG 中,坐标轴的原点在左上角。 x 坐标为 0 将图形放在 SVG 区域的左边缘, y 坐标为 0 将图形放在 SVG 区域的上边缘。 x 值增大矩形将向右移动, y 值增大矩形将向下移动。

为了使条形图向上,需要改变 y 坐标计算的方式。 这需要计算条形的高度和 SVG 区域的总高度。

SVG 区域的高度为 100。 如果在集合中一个数据点的值为 0,那么条形将从 SVG 区域的最底端开始(而不是顶端)。 为此,y 坐标的值应为 100。 如果数据点的值为 1,你将从 y 坐标为 100 开始来将这个条形设置在底端, 然后需要考虑该条形的高度为 1,所以最终的 y 坐标将是 99。

y 坐标为 y = heightOfSVG - heightOfBar 会将条形图向上放置。

实操

改变 y 属性的回调函数,让条形图向上放置。 height 的值是 3 倍 d 的值。

注意: 通常,关系是 y = h - m * d,其中 m 是缩放数据点的常数。

  1. 第一个 rect 的 y 值应该为 64。
  2. 第二个 rect 的 y 值应该为 7。
  3. 第三个 rect 的 y 值应该为 34。
  4. 第四个 rect 的 y 值应该为 49。
  5. 第五个 rect 的 y 值应该为 25。
  6. 第六个 rect 的 y 值应该为 46。
  7. 第七个 rect 的 y 值应该为 13。
  8. 第八个 rect 的 y 值应该为 58。
  9. 第九个 rect 的 y 值应该为 73。
<body>
  <script>
    const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];

    const w = 500;
    const h = 100;

    const svg = d3.select("body")
                  .append("svg")
                  .attr("width", w)
                  .attr("height", h);

    svg.selectAll("rect")
       .data(dataset)
       .enter()
       .append("rect")
       .attr("x", (d, i) => i * 30)
       .attr("y", (d, i) => {
    
          return h - (3 * d)

       })
       .attr("width", 25)
       .attr("height", (d, i) => 3 * d);
  </script>
</body>