Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

338
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda