网站搜索

javascript - 点击时从一个元素向多个元素绘制一条线


我正在尝试从元素 [.identifier] 画一条线到被点击的元素 [A, B, C 系列]。我能够显示这条线,但方向相反,不确定为什么会这样显示。这里是我的 fiddle: https://jsfiddle.net/SampathPerOxide/u2afymxs/11/ 有没有人能帮我显示一个从 ".identifier" 到相应系列元素的连线?

点击 A 系列后的预期结果:

点击 B 系列时:

$('.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>

答案#1

我修好了你的 fiddle: https://jsfiddle.net/c4ju6a0p/

代码更改:

// 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;

  • 问题是该行由于 relative 定位而使用了错误的位置进行计算。当 relative CSS 被注释掉时,这一点可以更清楚地看到: https://jsfiddle.net/vust5nxf/
  • 另外,如果你希望线条延伸到左边缘,不要加上 offsetWidth。

更新:没有注意到代码片段...也在那里应用了更改。我还做了一个额外的更改:

  • 你需要将被点击的元素传递给 adjustLine(),否则当前每次绘制的线都会在相同的两个元素之间,因为这些元素的 ID 是硬编码的。
  • 作为一个风格提示:我会把函数 adjustLine() 的定义移到点击处理程序之外。这样代码会更易读,而且函数只会创建一次,而不是每次处理点击时都创建一次。
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>