jsPlumb: how to make Flowchart connectors avoid intersecting elements?
Asked Answered
E

4

22

Is it possible to make jsPlumb Flowchart connectors not to cross connectable items or specified elements (in the example: elements with 'item' class)?

Default Flowchart behaviour:

enter image description here

A desired result:

enter image description here

Here's what I tried:

http://jsfiddle.net/CcfTD/1/

Edited to clarify

HTML

 <div id="root">
        <div class="item" id="item1">Item 1</div>
        <div class="item" id="item2">Item 2</div>
        <div class="item" id="item3">Item 3</div>
        <div class="item" id="item4">Item 4</div>
        <div class="item" id="item5">Item 5</div>
  </div>

JS

   jsPlumb.connect({
    source: $('#item2'),
    target: $('#item7'),
    anchors: [ "Continuous" ],
    connector:[ "Flowchart" ],
    paintStyle: {
        strokeStyle: "#000000", 
        lineWidth:1
    }
});

Basically to have jsPlumb engine (SVG or canvas) be aware of the relevant DOM elements and have a object-avoidance scheme

http://jsfiddle.net/adardesign/2ZFFc/

Estrellaestrellita answered 16/5, 2012 at 15:39 Comment(2)
Seems to be implemented here for the connected items - lines curve around them instead of passing through.Deraign
@star, thanks for the clue, and idea how I can use flowchart.com outside of their platform ?Legislation
T
6

While I am actually trying to find a proper method for doing this (which led me to your question). I do have a solution that I am using in the meanwhile to get jsPlumb to work in the way that I want it to.

Basically you have to add in a zero height/width div to act as an intermediate node. You then make connections to and from that node instead of directly between the real items.

I have modified your jsfiddle (updated link) to provide an example of this.

The important things to note are ability to set the anchor placement using coordinates and the ability to use two different endpoint shapes. In addition, since the default length from the anchor to the first turn is too long in your example, it can be controlled by using the stub argument.

Below are the relevant modifications with comments.

HTML

<div id="root">
    <div class="item" id="item1">Item 1</div>
    <div class="item" id="item2">Item 2</div>
    <div class="item" id="item3">Item 3</div>
    <div class="item" id="item4">Item 4</div>
    <div class="item" id="item5">Item 5</div>
    <div class="item" id="item6">Item 6</div>
    <div class="item" id="item7">Item 7</div>
    <div class="node" id="8-12"></div>            <!-- Midpoint -->
    <div class="item" id="item8">Item 8</div>
    <div class="item" id="item9">Item 9</div>
    <div class="item" id="item10">Item 10</div>
    <div class="item" id="item11">Item 11</div>
    <div class="item" id="item12">Item 12</div>
    <div class="item" id="item13">Item 13</div>
    <div class="item" id="item14">Item 14</div>
</div>

CSS

.node {
    position: absolute;
    height: 0px;
    width: 0px;
    visibility: hidden;

    /* change these to place the midpoint properly */
    left: 285px;
    top: 160px;
}

JS

//connection from item8 to midpoint(8-12)
jsPlumb.connect({
    source: $('#item8'),
    target: $('#8-12'),
    connector:[ "Flowchart", {stub:5} ], //<== set stub length to be
                                         //    as short as you need it
    paintStyle: {
        strokeStyle: "#000000", 
        lineWidth:1
    },
    anchors:[ [0,0.5,-1,0],[0.5,0,0,-1] ], //<== connection position/direction
    endpoints:[ ["Dot", {radius:2}],["Blank"] ] //<== Blank connector at end
});

//connection from midpoint(8-12) to item12
jsPlumb.connect({
    source: $('#8-12'),
    target: $('#item12'),
    connector:[ "Flowchart", {stub:5} ], //<== set stub length to be
                                         //    as short as you need it
    paintStyle: {
        strokeStyle: "#000000", 
        lineWidth:1
    },
    anchors:[ [0,0.5,-1,0],[0.5,0,0,-1] ], //<== connection position/direction
    endpoints:[ ["Blank"],["Dot", {radius:2}] ] //<== Blank connector at start
});
Trachytic answered 1/2, 2013 at 16:31 Comment(2)
Thanks so much! It seems like your going in a certain direction, but its not complete, could you please modify and show the complete solution.. ?Legislation
Hey, one possible solution could be to grab the divs bounds and put them in a two dimensional array, like here: https://mcmap.net/q/658231/-detecting-div-collision Then we could dynamically place this anchors and avoid collisions... for what I want to do I also want this connections to be parallel to each other(e.g.: They don't run straight over each other), with this in mind we could also add some rules like some distance between the divs and other connectionsProfit
C
2

Actually, the solution to your problem is deeper, especially if you're working with dynamic data.

After some hours of digging I finally found a "crack", not a pretty solution, but a crack.

I just did this change for Flowchart connectors, also I am not familiar at all with the other connectors, never used them.

After considering various things like midx and midy and initial stubs (those should be used in the complete solution but I abandoned them), simplest thing to do is to search for the addSegment function in connectors-flowchart.js file. That's where the segments are added.

Prior to adding the current segment (push it in the segments array), you check if it will intersect with any of your elements, just calculate some intermediary points (thus adding additional segments, breaking the initial one into pieces) so it basically takes a detour around the intersected element.

If more details are needed, I'd be happy to share.

Caballero answered 31/12, 2013 at 12:11 Comment(2)
I added an additional step in my "avoid nodes" code: after adding the auxiliary segments meant to detour blocks, I also added a cleanup method, that basically shortens the segments array if unnecessary segments are found (if 2 segments that are not consecutive can be otherwise connected by a lesser number of segments, then the current segments are removed and new segments are added).Caballero
Also, I edited midpoint (set it to 1 or 0.7 depending on the end point anchor position). Examples:imageshack.us/photo/my-images/829/ksxa.jpg and imageshack.us/photo/my-images/844/hny3.jpgCaballero
S
2

I just had a similar problem, where connections of a dynamically generated diagram intersected with elements.

What worked for me was to specify the "midpoint" argument for the Flowchart connection. Maybe this helps in you case as well.

The stub argument also accepts arrays (not in documentation). I just set:

jsPlumb.Defaults.Connector = [ "Flowchart", { stub: [10, 50], midpoint: 0.0001 } ];

Hope this helps!

Sos answered 8/1, 2014 at 14:33 Comment(0)
I
1

I've tried out the above options and if you just want a simple solution without adding middle nodes, the following worked for me:

connector: ["Flowchart", { anchors: ["Bottom", "Top"] }]

Add those params on your connect.

Investigator answered 9/10, 2019 at 9:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.