Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

337
Views
Draw a line from one element to multiple elements on click

I'm trying to draw a line from an element [.identifier] to the clicked element [ A, B, C series ]. I'm able to display the line but in the other direction, not sure why it is displaying in such a direction. Here is my fiddle: https://jsfiddle.net/SampathPerOxide/u2afymxs/11/ Can someone help me to display a line between ".identifier" and the respective series element?

Expected result on clicking A series: enter image description here on clicking B series: enter image description here

$('.seriesli').click(function() {

  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';
  }
  adjustLine(
    document.getElementById('div1'),
    document.getElementById('div2'),
    document.getElementById('line')
  );
});
.identifier {
  width: 10px;
  height: 10px;
  background-color: red;
  position: absolute;
  right: 45%;
  top: 50%;
}

.series-div {
  position: absolute;
  right: 5%;
  bottom: 30%;
}

.series-ul li {
  list-style: none;
  color: grey;
  font-size: 1em;
  font-weight: 600;
  border: 2px solid grey;
  display: table;
  padding: 0.3em 0.1em;
  text-align: center;
  margin: 0.5em;
  cursor: pointer;
}

#line {
  position: absolute;
  width: 2px;
  margin-top: -1px;
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="position;relative;">
  <div class="identifier" id="div2"></div>
  <div class="series-div">
    <ul class="series-ul">
      <li class="seriesli" id="div1">A series</li>

      <li class="seriesli">B series</li>
  
      <li class="seriesli">C series</li>
    
    </ul>
  </div>
   <div id="line"></div>
  <img src="https://stat.overdrive.in/wp-content/odgallery/2020/06/57263_2020_Mercedes_Benz_GLS.jpg" class="img-responsive firstcar-detail" style="width: 100%;">

</div>

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

I fixed your fiddle: https://jsfiddle.net/c4ju6a0p/

Code changes:

// Get actual position relative to viewport.
// See https://stackoverflow.com/a/11396681/117030
fromBCR = from.getBoundingClientRect();
toBCR   = to.getBoundingClientRect();

var fT = fromBCR.top + from.offsetHeight / 2;
var tT = toBCR.top + to.offsetHeight / 2;

// Don't add offsetWidth. This connects to the middle, not the left edge.
var fL = fromBCR.left //+ from.offsetWidth / 2;
var tL = toBCR.left + to.offsetWidth / 2;

  • The problem was the line was being calculated with the incorrect position due to relative positioning. This can be seen more clearly when the relative CSS is commented out: https://jsfiddle.net/vust5nxf/
  • Also, don't add the offsetWidth if you want the line to go to the left edge.

update: didn't notice the code snippet... applied changes there, too. I also made one more change:

  • You need to pass the element that was clicked to adjustLine(), otherwise currently the line is drawn between the same two elements every time because the elements are hardcoded with ids.
  • As a style note: I would move the definition of function adjustLine() outside the click handler. This will make the code easier to read, and the function will only be created once, instead of every time a click is handled.
adjustLine(
  this, // Element that was clicked.
  document.getElementById('div2'),
  document.getElementById('line')
);

$('.seriesli').click(function() {

  function adjustLine(from, to, line) {

    // Get actual position relative to viewport.
    // See https://stackoverflow.com/a/11396681/117030
    fromBCR = from.getBoundingClientRect();
    toBCR   = to.getBoundingClientRect();
    
    var fT = fromBCR.top + from.offsetHeight / 2;
    var tT = toBCR.top + to.offsetHeight / 2;
    
    // Don't add offsetWidth. This connects to the middle, not the left edge.
    var fL = fromBCR.left //+ from.offsetWidth / 2;
    var tL = toBCR.left + 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';
  }
  adjustLine(
    this, // Element that was clicked.
    document.getElementById('div2'),
    document.getElementById('line')
  );
});
.identifier {
  width: 10px;
  height: 10px;
  background-color: red;
  position: absolute;
  right: 45%;
  top: 50%;
}

.series-div {
  position: absolute;
  right: 5%;
  bottom: 30%;
}

.series-ul li {
  list-style: none;
  color: grey;
  font-size: 1em;
  font-weight: 600;
  border: 2px solid grey;
  display: table;
  padding: 0.3em 0.1em;
  text-align: center;
  margin: 0.5em;
  cursor: pointer;
}

#line {
  position: absolute;
  width: 2px;
  margin-top: -1px;
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="position;relative;">
  <div class="identifier" id="div2"></div>
  <div class="series-div">
    <ul class="series-ul">
      <li class="seriesli" id="div1">A series</li>

      <li class="seriesli">B series</li>
  
      <li class="seriesli">C series</li>
    
    </ul>
  </div>
   <div id="line"></div>
  <img src="https://stat.overdrive.in/wp-content/odgallery/2020/06/57263_2020_Mercedes_Benz_GLS.jpg" class="img-responsive firstcar-detail" style="width: 100%;">

</div>

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!