Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connect Line Between 2 Elements - Javascript

I'm currently working on a way to create a single-line diagram using Javascript. I'm currently able to connect two html elements using the following function:

adjustLine (from, to, line) {
  var fT = from.offsetTop  + from.offsetHeight/2;
  var tT = to.offsetTop      + to.offsetHeight/2;
  var fL = from.offsetLeft + from.offsetWidth/2;
  var tL = to.offsetLeft     + to.offsetWidth/2;

  var CA   = Math.abs(tT - fT);
  var CO   = Math.abs(tL - fL);
  var H    = Math.sqrt(CA*CA + CO*CO);
  var ANG  = 180 / Math.PI * Math.acos( CA/H );

  if(tT > fT){
      var top  = (tT-fT)/2 + fT;
  }else{
      var top  = (fT-tT)/2 + tT;
  }
  if(tL > fL){
      var left = (tL-fL)/2 + fL;
  }else{
      var left = (fL-tL)/2 + tL;
  }

  if(( fT < tT && fL < tL) || ( tT < fT && tL < fL) || (fT > tT && fL > tL) || (tT > fT && tL > fL)){
    ANG *= -1;
  }
  top-= H/2;

  line.style["-webkit-transform"] = 'rotate('+ ANG +'deg)';
  line.style["-moz-transform"] = 'rotate('+ ANG +'deg)';
  line.style["-ms-transform"] = 'rotate('+ ANG +'deg)';
  line.style["-o-transform"] = 'rotate('+ ANG +'deg)';
  line.style["-transform"] = 'rotate('+ ANG +'deg)';
  line.style.top    = top+'px';
  line.style.left   = left+'px';
  line.style.height = H + 'px';
}

The function takes 3 parameters:

  • 1) the first html element
  • 2) the second html element
  • 3) the line that connects the elements.

This works fine and outputs the following result:

enter image description here

However, the lines that connect the html elements are a straight line, I would like to have a more natural flow for a diagram, something like the following:

enter image description here

Any advice on how I could go about doing this? Any help is greatly appreciated!

Edit

I'm using html2canvas to create an image of the generated output. This is my code:

var myDiv = document.getElementById('content');

html2canvas(myDiv, {useCORS: true, allowTaint : true}).then(function (canvas) {

            var imgData = canvas.toDataURL("image/png", 1.0);
            var imgData2 = canvas2.toDataURL("image/png", 1.0);

            var pdf = new jsPDF('l', 'pt', [HTML_Width, HTML_Height]);
            pdf.internal.scaleFactor = 30;
            pdf.addImage(imgData, 'PNG', 0, 0, HTML_Width, HTML_Height);

            pdf.addPage();
            pdf.addImage(imgData2, 'PNG', 0, 0, HTML_Width_2, HTML_Height_2);

            pdf.save("my_file.pdf");
});
like image 318
Brian Moreno Avatar asked Feb 23 '20 16:02

Brian Moreno


People also ask

How do you put two elements on the same line?

#Using display: inline-block To get all elements to appear on one line the easiest way is to: Set white-space property to nowrap on a parent element; Have display: inline-block set on all child elements.

How do I add a line between elements in HTML?

To create line breaks in HTML, use the <br> tag. There is no closing tag necessary. In the code above, there will be a line break between "125 N 6th St" and "Brooklyn, NY 11249" that won't have the outrageous amount of space that appears between two paragraph elements.

How do I draw a line between two divs?

HTML provides <hr> tag to draw horizontal line between two elements. You can also use <hr> tag between two divs to separate them properly.


1 Answers

So heree is my solution with SVG!

const xmlns   = 'http://www.w3.org/2000/svg'
  ,   svgLink = 'http://www.w3.org/1999/xlink'
  ,   elmSVG  = document.getElementById('elmSVG')
  ,   bot_inversor  = 80
  ,   top_fotovolta = 300
  ;
for (let i=0;i<4;i++)
  {
  let x = 10 + (i*60)
    , fotovolta = document.createElementNS(xmlns, 'use');

  fotovolta.setAttributeNS(svgLink, 'xlink:href', '#fotovoltaico');

  fotovolta.setAttributeNS(null, 'x', x);
  fotovolta.setAttributeNS(null, 'y', top_fotovolta);
  fotovolta.setAttributeNS(null, 'width', '50');
  fotovolta.setAttributeNS(null, 'height', '70'); 

  elmSVG.appendChild(fotovolta);

  adjustLines(i);
  }
function adjustLines(item)
  {
  let left = (item<2)    // the hard part...  
    , b1 = 25 + (item *60) + (left?0:20)
    , b2 = b1 + (left?20:-20)
    , a1 = 105 + (item *10) + (left?0:10)
    , a2 = a1 + (left?5:-5)
    , l1 = 50 + (left?item:3-item) *30
    , l2 = l1 + 10
    ;
  let jLine1 = document.createElementNS(xmlns, 'polyline');
  jLine1.setAttributeNS(null, 'points', `${b1},${top_fotovolta} ${b1},${bot_inversor+l1} ${a1},${bot_inversor+l1} ${a1},${bot_inversor}`);
  elmSVG.appendChild(jLine1);   

  let jLine2 = document.createElementNS(xmlns, 'polyline');
  jLine2.setAttributeNS(null, 'points', `${b2},${top_fotovolta} ${b2},${bot_inversor+l2} ${a2},${bot_inversor+l2} ${a2},${bot_inversor}`);
  elmSVG.appendChild(jLine2);   
  }
#elmSVG {
  width: 250px;
  height: 380px;
  background-color: #b4f0f0;
  margin: 1em;
}
#elmSVG * {
  fill:none;
  stroke:#2f363d;
  stroke-width:2px;
}
.curveSVG {
  stroke-linecap:round;
}
<h2>Connecting Lines</h2>

<svg id="elmSVG" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 380">
  <defs>
    <symbol id="inversor" viewBox="0 0 70 70">
      <rect x="0" y="0" width="70" height="70" />
      <line x1="70" x2="0" y1="0" y2="70"  />
      <line x1="10" x2="30" y1="15" y2="15" />
      <line x1="10" x2="30" y1="20" y2="20"  />
      <path d="M 40,55 Q 45,45 50,55 T 60,55" class="curveSVG" />
    </symbol>
    <symbol id="fotovoltaico"  viewBox="0 0 50 70">
      <rect x="0" y="0" width="50" height="70" />
      <line x1="0" x2="25" y1="0" y2="20"  />
      <line x1="50" x2="25" y1="0" y2="20"  />
    </symbol>
  </defs>

  <use xlink:href="#inversor" x="90"  y="10" width="70" height="70" />
</svg>
like image 129
Mister Jojo Avatar answered Sep 20 '22 04:09

Mister Jojo