在BIG矩形内添加小矩形,在D3中使用唯一的ID和链接?在特定ID之后

时间:2017-04-13 20:54:40

标签: javascript d3.js

在上一个问题中,我问过如何为生成的矩形here

生成唯一ID

现在,我一直在尝试在这些矩形内绘制小矩形。但是,id="rectup0"只能有4个具有唯一xlink:href属性的小型矩形 其余的可以在里面有2个矩形。

<body>
<div id="chart">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.js"></script>

    <script type="text/javascript">

      var width = 1000,
          height = 250,
          margin = 7,
          nRect = 11,
          rectWidth = (width - (nRect - 1) * margin) / nRect,

          svgContainer = d3.select('#chart').append('svg')
              .attr('width', width)
              .attr('height', height),

          svgWalkway = d3.select('#chart').append('svg')
            .attr('width', '1000')
            .attr('height', '150'),

          svgContainer2 = d3.select('#chart').append('svg')
            .attr('width', width)
            .attr('height', height);


// Rectangles scaling

      var firstRow = d3.range(nRect),
          posxScale = d3.scaleLinear()
            .domain(d3.extent(firstRow))
            .range([0, width - rectWidth]);

      var middleRow = d3.range(1),
          posxScale3 = d3.scaleLinear()
            .domain(d3.extent(middleRow))
            .range([0, width - rectWidth]);

      var secondRow = d3.range(nRect),
          posxScale2 = d3.scaleLinear()
            .domain(d3.extent(secondRow))
            .range([0, width - rectWidth]);

      //Drawing the actual objects HTML rects    
      svgContainer.selectAll('rect.up')
        .data(firstRow)
        .enter()
        .append('rect')
        .attr("id", function(d,i){ return "rectup" + i })
        .attr('x', posxScale)
        .attr('width', rectWidth)
        .attr('height', height)
        .attr('class','up');

      svgWalkway.selectAll('rect.middle')
        .data(middleRow)
        .enter()
        .append('rect')
        .attr('x', posxScale3)
        .attr('width','1000')
        .attr('height','150')
        .attr('class', 'middle');


      svgContainer2.selectAll('rect.down')
        .data(secondRow)
        .enter()
        .append('rect')
        .attr('id', function (d,i) { return "rectdown" + i })
        .attr('x', posxScale2)
        .attr('width', rectWidth)
        .attr('height', height)
        .attr('class', 'down')
        .attr('y', 0);
    </script>
</div>
</body>

我尝试绘制类似前面的矩形(使用.append()),但到目前为止只是将它们放在svgContainer旁边。我一直在阅读一些关于使用分组的帖子,试过但没有用。提前致谢

更新

所以基本上,整个问题可以恢复为在 rect之后向添加rect id="rectup0"标记,以便我可以

<rect id="rectup0"></rect>
<rect id="redrect" x="0" width="20" height="40"></rect>

我知道JQuery允许您将类属性添加到其他类,但不确定D3,这将类似于以编程方式添加新的rect标记。甚至可能吗?

更新2

我想可以d3.insert使用以下内容:

d3.select('#rectup0').insert('rect')
  .attr('id', 'redrect')
  .attr('x', 0)
  .attr('width', '20')
  .attr('height', '40');

然而,它会在开头的中间得到它并关闭rect标签,如此

<rect id="rectup0">
    <rect id="redrect" x="0" width="20" height="40"></rect>
</rect>

毋庸置疑,由于结束rect代码

,这不起作用

1 个答案:

答案 0 :(得分:0)

您可以使用each包装器为所选数据执行此操作。它接受3个参数:当前数据d,当前索引i和整个数据数组arr。所以如果你需要某种检查,你是否应该附加小rect,你可以创建一个辅助函数:

var testIndex = function(d, i, arr) {
    return
      // test index
      i == 5 ||
      // test current data
      d == 10 ||
      // test other array members, which would be an EnterNode here
      (i > 0 && arr[i - 1]['__data__'] == 7);  
}

// do checks in one line:
var testIndex = function (d, i, arr) { return i == 4 || i == 10 || i == 7; }

var data = svgContainer.selectAll('rect.up')
  .data(firstRow);

data
  .enter()
  .each(function (d, i, arr) {
    // select DOM element to add the rects
    t = d3.select(this);

    t
      .append('rect')
      // note that here we use empty the parameters list
      .attr('id', 'rectup' + i)
      .attr('x', posxScale)
      .attr('width', rectWidth)
      .attr('height', height)
      .attr('class','up');

    if (!testIndex(d, i, arr)) {
      return;
    }

    t
      .append('rect')
      .attr('id', 'redrect' + i)
      // note that we need to define x-coord similar to first rect
      .attr('x', posxScale)
      .attr('class', 'redrect');
});

// remove your data before redraw
data
  .exit()
  .remove();

输出:

<svg width="1000" height="250">
  <rect id="rectup0" x="0" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup1" x="91.54545454545456" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup2" x="183.09090909090912" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup3" x="274.6363636363636" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup4" x="366.18181818181824" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup5" x="457.72727272727275" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="redrect5" x="457.72727272727275" class="redrect"></rect>
  <rect id="rectup6" x="549.2727272727273" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup7" x="640.8181818181818" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="redrect7" x="732.3636363636365" class="redrect"></rect>
  <rect id="rectup8" x="732.3636363636365" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup9" x="823.909090909091" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="rectup10" x="915.4545454545455" width="84.54545454545455" height="250" class="up"></rect>
  <rect id="redrect10" x="915.4545454545455" class="redrect"></rect>
</svg>

此方法的缺点是您无法提供attr参数作为JSON:

// wouldn't work
.attr({
  id: 'redrect',
  x: posxScale,
  width: '20',
  height: '40'
});