d3自定义刻度线(基于nextSibling) [英] d3 customize tick line (based on nextSibling)

查看:39
本文介绍了d3自定义刻度线(基于nextSibling)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的数据(在y轴上)有间隙,所以即使我宁愿使用线性标尺,也必须使用序数标尺—.这样就看不到孔了.

I have gaps in my data (on the y-axis), so even though I'd rather use a linear scale, I have to go with an Ordinal scale — so that the holes are not seen.

但是,我确实想使用不同的刻度标记直观地显示数据不是连续的.这里的想法是检查下一个值-当前值是否为1,如果不绘制其他刻度线.

However, I do want to visually show that the data was not continuous using a different tick marker. The idea here is to check if the next value - current value is 1, and if not draw a different tick line.

使用此示例我使用了 this.parentNode.nextSibling —但没有得到所需的值.

Using this example I used this.parentNode.nextSibling — but it's not getting the required value.

我该怎么做?

下面的示例代码.我希望2、5和8的行显示在不同的刻度中(例如 stroke-dasharray:"10,2" 或可能是不同的颜色)

Sample code below. I would want the lines for 2, 5 and 8 show up in a different tick (say stroke-dasharray: "10,2" or may be a different color)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Ticks problem</title>
  </head>
  <body>

    <svg width="500" height="300"></svg>

    <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
    <script type="text/javascript">
      var svg = d3.select("svg"),
        margin = {top: 20, right: 0, bottom: 20, left: 0},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      var data = [5, 15, 7, 10, 4, 12, 14];

      var yDomain = [1, 2, 4, 5, 8, 10, 11];
      var yRange  = Array(data.length+1).fill().map((d,i)=>(i+1)*35);
      var yScale = d3.scaleOrdinal()
          .domain(yDomain)
          .range(yRange);

      var yAxis = d3.axisRight(yScale)
        .ticks(data.length+1)
        .tickSize(width);

      function customYAxis(g) {
        g.call(yAxis);
        g.attr("id", "y-axis");
        g.select(".domain").remove();
        //g.selectAll(".tick line").attr("stroke", "#777").attr("stroke-dasharray", "2,2");
        g.selectAll(".tick line")
        .attr("stroke", "#777")
        .attr("stroke-dasharray", (d,i)=>{
          //let n = d3.select(this.parentNode.nextSibling).datum(); // not working
          //console.log(i + " " + d+" "+n);
          // return "10,2" if n-d > 1
          return "2,2"; // return some default for now
        })
        g.selectAll(".tick text").attr("x", 4).attr("dy", -4);
      }

      g.append('g').call(customYAxis);
    </script>

  </body>
</html>

推荐答案

请记住, <代码> selection.attr() 将被调用,并提供三个参数:

传递了当前数据( d ),当前索引( i )和当前组( nodes ),其中 this 作为当前DOM元素( nodes [i] )

being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i])

您可以使用第三个参数来访问下一个元素的数据.由于 i 是当前元素的索引,因此 node [i + 1] 将指向下一个元素.您可以轻松地选择下一个元素,然后使用 .datum()检索绑定的基准.

You can make use of the third argument to access the datum of the next element. Since i is the index of the current element, node[i+1] will point to the next element. You can easily select that next element and use .datum() to retrieve the bound datum.

d3.select(nodes[i+1]).datum()

剩下的唯一事情就是采用一种保护措施,以免读取到 nodes 数组中的最后一个元素.

The only thing left is to employ a safeguard to not read past the last element in the nodes array.

i < nodes.length - 1 && d3.select(nodes[i+1]).datum()

这可以直接在您的 .attr()设置器中使用:

This can directly be used in your .attr() setter:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Ticks problem</title>
  </head>
  <body>

    <svg width="500" height="300"></svg>

    <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
    <script type="text/javascript">
      var svg = d3.select("svg"),
        margin = {top: 20, right: 0, bottom: 20, left: 0},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      var data = [5, 15, 7, 10, 4, 12, 14];

      var yDomain = [1, 2, 4, 5, 8, 10, 11];
      var yRange  = Array(data.length+1).fill().map((d,i)=>(i+1)*35);
      var yScale = d3.scaleOrdinal()
          .domain(yDomain)
          .range(yRange);

      var yAxis = d3.axisRight(yScale)
        .ticks(data.length+1)
        .tickSize(width);

      function customYAxis(g) {
        g.call(yAxis);
        g.attr("id", "y-axis");
        g.select(".domain").remove();
        //g.selectAll(".tick line").attr("stroke", "#777").attr("stroke-dasharray", "2,2");
        g.selectAll(".tick line")
        .attr("stroke", "#777")
        .attr("stroke-dasharray", (d, i, nodes) => {
          return i < nodes.length - 1 && d3.select(nodes[i+1]).datum() - d > 1 ? "10,2" : "2,2";
        })
        g.selectAll(".tick text").attr("x", 4).attr("dy", -4);
      }

      svg.append('g').call(customYAxis);
    </script>

  </body>
</html>

这篇关于d3自定义刻度线(基于nextSibling)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆