San
San

Reputation: 23

Add link between the rectangles in d3 v4

I am new to d3, I have referred some examples and have introduced swimlanes. I have updated the code with whatever I have tried so far, but I am stuck with one problem here.

var lanedata = [
    {id: 0, label: "lane 0"},
    {id: 1, label: "lane 1"},
    {id: 2, label: "lane 2"},
    {id: 3, label: "lane 3"},
    {id: 4, label: "lane 4"},
    {id: 5, label: "lane 5"},
    {id: 6, label: "lane 6"},
];
                
var items_data = [
    {id: 10, label: "lane 0", start: 0,end:3, lane:0, source:1,target:"col 1"},
    {id: 11, label: "lane 0", start: 1,end:4, lane:0, source:2,target:"col 2"},
    {id: 12, label: "lane 0", start: 5,end:3, lane:0, source:3,target:"col 3"},
    {id: 13, label: "lane 0", start: 8,end:7, lane:0, source:4,target:"col 4"},
    {id: 7, label: "lane 1", start: 0,end:8, lane:1, source:5,target:"col 5"},
    {id: 8, label: "lane 1", start: 1,end:7, lane:1, source:6,target:"col 6"},
    {id: 9, label: "lane 1", start: 5,end:8, lane:1, source:7,target:"col 7"},
    {id: 14, label: "lane 1", start: 8,end:7, lane:1, source:8,target:"col 4"},
    {id: 15, label: "lane 2", start: 1,end:7, lane:2, source:9,target:"col 4"},
    {id: 16, label: "lane 2", start: 2,end:7, lane:2, source:0,target:"col 4"},
    {id: 17, label: "lane 2", start: 5,end:7, lane:2, source:8,target:"col 4"},
    {id: 18, label: "lane 3", start: 2,end:7, lane:3, source:8,target:"col 4"},
    {id: 19, label: "lane 3", start: 3,end:7, lane:3, source:8,target:"col 4"},
    {id: 20, label: "lane 3", start: 5,end:7, lane:3, source:8,target:"col 4"},
    {id: 21, label: "lane 3", start: 6,end:7, lane:3, source:8,target:"col 4"},
    {id: 22, label: "lane 4", start: 2,end:7, lane:4, source:8,target:"col 4"},
    {id: 23, label: "lane 4", start: 3,end:7, lane:4, source:8,target:"col 4"},
    {id: 24, label: "lane 4", start: 5,end:7, lane:4, source:8,target:"col 4"},
    {id: 25, label: "lane 4", start: 6,end:7, lane:4, source:8,target:"col 4"},
    {id: 26, label: "lane 5", start: 2,end:7, lane:5, source:8,target:"col 4"},
    {id: 27, label: "lane 5", start: 3,end:7, lane:5, source:8,target:"col 4"},
    {id: 28, label: "lane 5", start: 5,end:7, lane:5, source:8,target:"col 4"},
    {id: 29, label: "lane 5", start: 6,end:7, lane:5, source:8,target:"col 4"},
    {id: 30, label: "lane 6", start: 0,end:7, lane:6, source:8,target:"col 4"},
    {id: 31, label: "lane 6", start: 1,end:7, lane:6, source:8,target:"col 4"},
    {id: 32, label: "lane 6", start: 2,end:7, lane:6, source:8,target:"col 4"},
];

var lanes = lanedata;
var items = items_data;
var max_width = 0;
var max_width_array = [];

for (var i = 0; i < items_data.length; i++) {
  max_width_array.push(items_data[i].start);
}
max_width = Math.max.apply(null, max_width_array)


var margin = {
    top: 20,
    right: 15,
    bottom: 15,
    left: 60
  },
  width = 1100 - margin.left - margin.right,
  height = 900 - margin.top - margin.bottom,
  miniHeight = lanes.length * 17 + 50,
  mainHeight = height;


var x1 = d3.scaleLinear().domain([0, 8]).range([0, width]);


var y1 = d3.scaleLinear().domain([0, 10]).range([0, mainHeight]);
var y2 = d3.scaleLinear().domain([0, 10]).range([0, miniHeight]);

var chart = d3.select('svg')
  .attr('width', width + margin.right + margin.left + margin.right + margin.left + margin.right + margin.left)
  .attr('height', height + margin.top + margin.bottom)
  .attr('class', 'chart');

chart.append('defs')
  .attr('id', 'clip')

  .append('rect')
  .attr('width', width)
  .attr('height', mainHeight);

var main = chart.append('g')
  .attr('transform', 'translate(' + 150 + ',' + 90 + ')')
  .attr('width', width)
  .attr('height', mainHeight)
  .attr('class', 'main')



main.append('g')
  .attr('transform', 'translate(0,' + mainHeight + ')')
  .attr('class', 'main axis date');

var rects = main.selectAll('rect')
  .data(items, function(d) {
    return d.id;
  })

// draw the lanes for the main chart
main.append('g').selectAll('.laneLines')
  .data(lanes)
  .enter().append('line')
  .attr('x1', 0)
  .attr('y1', function(d) {
    return Math.round(y1(d.id)) + 1.5;
  })
  .attr('x2', width + 250)
  .attr('y2', function(d) {
    return Math.round(y1(d.id)) + 1.5;
  })
  .attr('stroke', function(d) {
    return d.label === '' ? '#c7ced9' : '#202124'
  });


main.append('g').selectAll('.laneLines_1')
  .data(items)
  .enter().append('line')
  .attr('x1', function(d) {
    return Math.round(x1(d.source)) - 1.5;
  })
  .attr('y1', -20)
  .attr('x2', function(d) {
    return Math.round(x1(d.source)) - 1.5;
  })
  .attr('y2', height - 250)
  .attr('stroke', function(d) {
    return d.label === '' ? 'black' : '#202124'
  })
  .attr('class', function(d) {
    if (d.source == 0 || d.source == 1 || d.source == 5 || d.source == 8) {
      return 'solid';
    } else {
      return 'dashed'
    }
  });

main.append('g').selectAll('.laneText')
  .data(lanes)
  .enter().append('text')
  .text(function(d) {
    return d.label;
  })
  .attr('x', -10)
  .attr('y', function(d) {
    return y1(d.id + .5);
  })
  .attr('dy', '0.5ex')
  .attr('text-anchor', 'end')
  .attr('class', 'laneText');


rects.enter().append('rect')
  .attr('x', function(d) {
    if (d.id == 9 || d.id == 12 || d.id == 13 || d.id == 14)
      return x1(d.start) - 60;
    else
      return x1(d.start) + 10;
  })
  .attr('y', function(d) {
    return y1(d.lane) + 3
  })
  .attr('width', function(d) {
    if (d.source == 6)
      return 220;
    else
      return 110;
  })
  .attr('height', function(d) {
    return .8 * y1(1);
  })
  .attr('class', "rect_low")
  .attr('rx', 2)
  .attr("marker-end", "url(#end)")
  .attr('fill', "white");

var minExtent = 0;


rects.selectAll("text.label")
  .data(items)
  .enter().append("text")
  .attr("class", "label")
  .attr("x", function(d) {
    return x1(d.start);
  }).attr("y", function(d) {
    return y1(d.lane);
  })
  .style("text-anchor", "middle")
  .text("Class average");
.chart {
  shape-rendering: crispEdges;
}

.month text {
  text-anchor: start;
}

.todayLine {
  stroke: blue;
  stroke-width: 1.5;
}

.axis line,
.axis path {
  stroke: black;
}

.rect_low {
  fill: rgb(255, 255, 255);
  stroke-width: 1px;
  stroke: rgb(0, 0, 0);
}

.solid {
  stroke: solid;
  stroke-width: 2px;
}

.dashed {
  stroke-dasharray: 5, 5;
  fill: grey;
}

.triangle_label {
  fill: white;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

Here I want to add links/connectors/arrow between few of the rectangles,

Example: In lane 0 I want to add arrow between the rect 1 and rect 2.

Also is there a way where I can add connectors from any rect to other?

How can I achieve that?

Upvotes: 0

Views: 106

Answers (1)

marielle
marielle

Reputation: 438

You can use d3 data bind logic to link each datum to an svg line element. For example, use can do something like that:

main
  .append('g')
  .selectAll('line')
  .data(items_data)
  .enter()
  .append('line')
  .attr('x1', 100)
  .attr('x2', 300)
  .attr('y1', 100)
  .attr('y2', 100)
  .attr('stroke', 'red')

Instead of use fixed values for x1, x2, y1, y2 you have to compute them from you data, I don't know which should be the logic behind that but I suppose the depend on items_data values.

I suggest you to use d3 scales to compute these values and also the other ones you use to create rects and grid.

Upvotes: 1

Related Questions