pedrommuller
pedrommuller

Reputation: 16056

Connect shapes using an arrow in d3

I'm trying to connect 3 basic customs shapes using arrows, I took this arrow as reference.

I'd like to replicate the behavior of lucidchart for moving any shape, I've seen a lot of examples using the force layout, but I'm not sure if that is good candidate for what I'm trying to achieve, so any guidance will be appreciated.

this is my code:

var data =[{"x":"100.0","y":"100.0","name":"shape-0","id":"543fe9949382ed4a16c38cf3","type":"startEvent","index":0},{"x":"610","y":"100.0","name":"shape-1","id":"543fe9949382ed4a16c38cf5","type":"endEvent","index":1},{"x":"318","y":"93","name":"first task","id":"543fe9a09382ed4a16c38cf6","type":"task","index":2}];

var links = [
    {"source":{"x":136,"y":118},
     "target":{"x":318,"y":118}},
    {"source":{"x":428,"y":118},
     "target":{"x":610,"y":118}}];

var node = svg.selectAll('g').data(data)
    .enter()
    .append(function(d){
        return shapes[d.type](d).node();
    });

var link = svg.selectAll('.link')
.data(links).enter().append('g').attr('class', 'node')
.append('line')
.attr('class','path')
.style('stroke-width', 2)
.attr('marker-end', 'url(#arrow)');

link.selectAll("line").attr("x1", function(d){
      return d.source.x;
    }).attr("y1", function(d){
      return d.source.y;
    }).attr("x2", function(d){
      return d.target.x;
    }).attr("y2", function(d){
      return d.target.y;
    })

//arrows
svg.append('svg:defs').append('svg:marker')
.attr('id', 'arrow').attr('viewBox', '0 0 10 10')
.attr('refX', 0).attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 6)
.attr('orient', 'auto')
.append('svg:path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z');


svg.append('line')
.attr('x1', 5)
.attr('x2', 50)
.attr('y1', 5)
.attr('y2', 50)
.style('stroke', 'black')
.attr('stroke-width', 2)
.attr('marker-end', 'url(#arrow)');

This is the fiddle for reference. thanks in advance.

Upvotes: 2

Views: 2144

Answers (1)

meetamit
meetamit

Reputation: 25157

As I understand the question, I don't think you need a layout at all. Not if you're going for the lucid chart drag functionality.

You have your data array, which is your representation of all the shapes in the scene (a.k.a the model), including their x and y position. The goal should be to update those x and y props when a shape is dragged and then re-render all the shapes (via the usual enter, update, exit routine).

The concept of layout would become necessary if there is not an explicit x and y for each shape (like in the case of tree or partition layout) or perhaps if the x and y of each shape are supposed to be transformed into a different x and y (like in the case of force layout).

To implement dragging, you can use d3.behavior.drag(), like in this example. But unlike that example, you would want to modify the x and y property values of d, which is the shape's definition within data — not the DOM element's position as the example does.

Upvotes: 3

Related Questions