【问题标题】:stacking axes horizontally on top of each other将轴水平堆叠在彼此之上
【发布时间】:2015-12-12 13:02:22
【问题描述】:

This是 Mike Bostock 的一个“简单”蜂巢图示例(正如他所说的 in this article)。它具有由此代码创建的三个“轴”

svg.selectAll(".axis")
    .data(d3.range(3))
  .enter().append("line")
    .attr("class", "axis")
   .attr("transform", function(d) { return "rotate(" + degrees(angle(d)) + ")"; })
    .attr("x1", radius.range()[0]) 
    .attr("x2", radius.range()[1]);  

从第一个链接可以看到,三个“轴”形成一个圆圈,这似乎是通过上面代码的“变换”中的旋转以及使用angledegrees这些函数来完成的

var angle = d3.scale.ordinal().domain(d3.range(4)).rangePoints([0, 2 * Math.PI]),

function degrees(radians) {
  return radians / Math.PI * 180 - 90;
}

问题:如果只有两个“轴”,怎么可能(使用“平移”)将“轴”堆叠在一起(即作为两条相互平行的水平线?

在尝试执行此操作时,我尝试移除“轴”的旋转,然后将它们垂直隔开。为了停止旋转,我像这样删除了对“度”的调用

.attr("transform", function(d) { return "rotate(" + angle(d) + ")"; })

我还将角度的范围设置为 0,0

d3.scale.ordinal().domain(["one", "two"]).range([0,0]);

然后,为了分隔坐标轴,我添加了这样的“翻译”

.attr("transform", function(d) {return "translate(" + width /2 + "," + height/d + ")"});

结果是有一个可见的水平轴,似乎另一个存在,但只有当我将鼠标移到它上面时才能检测到(并且节点和线没有被重新定位)

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    不确定这是否是您所追求的,但可以通过以下方式实现垂直堆叠的两个“轴”:

    var angle = d3.scale.ordinal()
      .domain(d3.range(3)) //<-- only calculate angles for 2 [-90, 90]
      .rangePoints([0, 2 * Math.PI]),
    ...
    svg.selectAll(".axis")
      .data(d3.range(2)) //<-- 2 lines
    

    编辑

    您所描述的并不是真正的蜂巢图,尝试重新调整布局的用途可能比它的价值更麻烦。如果你只是想在一条线上链接点,这里有一个现成的实现:

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
    
    .link {
      fill: none;
      stroke-width: 1.5px;
    }
    
    .axis, .node {
      stroke: #000;
      stroke-width: 1.5px;
    }
    
    </style>
    <body>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script src="d3.hive.min.js"></script>
    <script>
    
    var width = 500,
        height = 500;
    
    var lineSep = 200,
        lineLen = 400,
        color = d3.scale.category10().domain(d3.range(20)),
        margin = [50,50];
    
    var nodes = [
      {x: 0, y: .1},
      {x: 0, y: .9},
      {x: 0, y: .2},
      {x: 1, y: .3},
      {x: 1, y: .1},
      {x: 1, y: .8},
      {x: 1, y: .4},
      {x: 1, y: .6},
      {x: 1, y: .2},
      {x: 1, y: .7},
      {x: 1, y: .8}
    ];
    
    var links = [
      {source: nodes[0], target: nodes[3]},
      {source: nodes[1], target: nodes[3]},
      {source: nodes[2], target: nodes[4]},
      {source: nodes[2], target: nodes[9]},
      {source: nodes[3], target: nodes[0]},
      {source: nodes[4], target: nodes[0]},
      {source: nodes[5], target: nodes[1]}
    ];
    
    var nodeNest = d3.nest().key(function(d){ return d.x }).entries(nodes);
    
    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + margin[0] + "," + margin[1] + ")");
    
    var axis = svg.selectAll(".axis")
        .data(nodeNest);
        
    var g = axis
      .enter().append("g")
      .attr("class", "axis")
      .attr("transform", function(d,i) { 
        var t = "translate(0," + (i * lineSep) + ")";
        return t;
      })
      .append("line")
      .attr("x1", 0)
      .attr("x2", lineLen);
    
    axis.selectAll(".node")
      .data(function(d){
        d.values.forEach(function(q){
          q.len = d.values.length;
        })
        return d.values;
      })
      .enter().append("circle")
      .attr("class", "node")
      .attr("cx", function(d, i, j) { 
        d.cx = ((i + 0.5) * (lineLen / d.len));
        d.cy =  (j * lineSep);
        return d.cx;
      })
     .attr("r", 5)
     .style("fill", function(d) { return color(d.x); });
     
    svg.selectAll(".link")
      .data(links)
      .enter().append("path")
      .attr("class", "link")
      .attr("d", function(d){
        console.log(d);
        var p = "";
        p += "M" + d.source.cx + "," + d.source.cy;
        p += "Q" + "0," + ((margin[1] / 2) + (lineSep/2));
        p += " " + d.target.cx + "," + d.target.cy;
        return p;
      })
      .style("stroke", function(d) { 
        return color(d.source.x); 
      });
    
    function degrees(radians) {
      return radians / Math.PI * 180 - 90;
    }
    
    </script>

    【讨论】:

    • 我很抱歉造成误解,但我真正想要的是水平堆叠它们(即两条水平线相互堆叠,之间有间距)。我玩过你的代码但无法弄清楚(部分原因是我不确定.rangePoints([0, 2*Math.PI]) 是否用于确定轴或节点的角度。无论如何你能告诉我如何水平堆叠它们非常感谢
    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多