如何制作一条曲线来连接 HTML 和 CSS 中的两个节点?

2024-04-24

我有两个 div,我想使用曲线图连接它们。知道我怎样才能实现这一目标吗? 如果运行下面提到的代码,您会看到有一个名为“命令序列启动”的标签。 和两个 div 分别是 W_SCMadl_refresh 和 WIN64_MCCMon,现在我想使用曲线连接这两个 div 到“命令序列启动”

.mv-thread,
.mv-sequence {
  display: inline-block;
}

.mv-sequence,
.mv-subsequence {
  border: solid 1px #e0e0e0;
  border-radius: 15px;
  margin: 85px;
  padding: 10px;
  text-align: center;
}

.mv-sequence>.title,
.mv-subsequence>.title {
  font-size: 17px;
  background-color: cadetblue;
  border-radius: 7px 0px;
  color: #fff;
  font-weight: bold;
  padding: 10px;
}

.mv-sequence>.body,
.mv-subsequence>.body {
  min-width: max-content;
  display: inline-block;
  text-align: left;
}

.mv-command>div.indicator {
  display: inline-block;
  width: 32px;
  height: 32px;
  line-height: 32px;
  border-radius: 32px;
  text-align: center;
  font-size: 17px;
}

.mv-command>span {
  font-size: 13px;
  font-weight: bold;
}

.mv-command:before {
  content: "";
  background-color: #000;
  width: 3px;
  height: 16px;
  display: block;
  margin-left: 14px;
}


/* for done*/

.mv-command.done:before {
  background: #477738;
}

.mv-cmd-done {
  background: #57b847;
}

.mv-cmd-done>a>span,
.mv-command.done>span {
  color: #477738;
}


/* for aborted*/

.mv-command.aborted:before {
  background: #844138;
}

.mv-cmd-aborted {
  background: #ea4f37;
}

.mv-cmd-aborted>a>span,
.mv-command.aborted>span {
  color: #844138;
}


/* for waiting*/

.mv-command.waiting:before {
  background-color: #808080;
}

.mv-cmd-waiting {
  background: #f1f1f1;
}

.mv-cmd-waiting>span,
.mv-command.waiting>span {
  color: #808080;
}


/* for disabled*/

.mv-command.disabled:before {
  background: #80808080;
}

.mv-cmd-disabled {
  border: 1px solid #80808080;
}

.mv-cmd-disabled>span,
.mv-command.disabled>span {
  color: #80808080;
}


/* for running */

.mv-command.running:before {
  background: #005686;
}

.mv-cmd-running {
  border: 1px solid #005686;
}

.mv-cmd-running>a>span {
  color: #80808080;
  animation: mymove 2s infinite;
}

@keyframes mymove {
  from {
    color: #fff;
  }
  to {
    color: #368ec4;
  }
}

.mv-command.running>span {
  color: #80808080;
  animation: mymove 2s infinite;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="styles.css">
  <title>ReleaseWork</title>
</head>

<body>
  <div>
    <div class="mv-sequence">
      <div class="body">
        <div class="mv-thread">
          <table style="width:100%">
            <span class="mv-sequence" style="background-color: green; color: aliceblue;">Command Sequence Starting</span>
            <tbody>
              <tr>
                <td style="vertical-align: top;">
                  <div>
                    <div class="body">
                      <div>
                        <div class="body">
                          <div class="mv-command done">
                            <span style="display:none" class="cmd-text">[ScmRefresh]</span>
                            <div data-state="Done" data-start="2020-10-22_18-13-49" data-end="2020-10-22_18-14-40" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_SCMadl_refresh.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                            <span>W_SCMadl_refresh</span>
                          </div>
                          <div class="mv-command done">
                            <span style="display:none" class="cmd-text">adl_photo</span>
                            <div data-state="Done" data-start="2020-10-22_18-14-40" data-end="2020-10-22_18-14-41" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_adl_photo.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                            <span>W_adl_photo</span>
                          </div>
                          <div class="mv-command done">
                            <span style="display:none" class="cmd-text">code:[ScmCollect]
        -cr_later</span>
                            <div data-state="Done" data-start="2020-10-22_18-14-42" data-end="2020-10-22_18-14-43" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_adl_collect.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                            <span>W_adl_collect</span>
                          </div>
                          <div class="mv-command done">
                            <span style="display:none" class="cmd-text">adl_collect_cr</span>
                            <div data-state="Done" data-start="2020-10-22_18-14-43" data-end="2020-10-22_18-14-44" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_adl_collect_cr.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                            <span>W_adl_collect_cr</span>
                          </div>
                          <div>
                            <div class="body">
                              <div class="mv-command aborted">
                                <span style="display:none" class="cmd-text">[ScmSync]</span>
                                <div data-state="Aborted" data-start="2020-10-22_18-14-44" data-end="2020-10-22_18-14-54" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-aborted"><a href="Main/MainThread/Release/Windows_SCM/Windows_SCM_sync/W_adl_sync.xml"><span
        class="fonticon fonticon-wrong"></span></a></div>
                                <span>W_adl_sync</span>
                              </div>
                              <div class="mv-command waiting">
                                <span style="display:none" class="cmd-text">[ScmAttach]
        -attached_fw_mod</span>
                                <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                                <span>W_adl_attach</span>
                              </div>
                            </div>
                          </div>
                          <div class="mv-command waiting">
                            <span style="display:none" class="cmd-text">adl_publish</span>
                            <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                            <span>W_adl_publish</span>
                          </div>
                          <div class="mv-command waiting">
                            <span style="display:none" class="cmd-text">code:[ScmDsWs]
        [workspace]</span>
                            <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                            <span>W_adl_ds_ws</span>
                          </div>
                        </div>
                      </div>
                      <div class="mv-thread">
                        <table style="width:100%">
                          <tbody>
                            <tr>
                              <td style="vertical-align: top;">
                                <div>
                                  <div class="body">
                                    <div>
                                      <div class="body">
                                        <div class="mv-command waiting">
                                          <span style="display:none" class="cmd-text">if not exist
        [WIN64_DRIVE]\[WIN64_DIR]\[PreqDir] mkdir
        [WIN64_DRIVE]\[WIN64_DIR]\[PreqDir]</span>
                                          <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="TCK" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                                          <span>W64_Shared_Preq_mkdir</span>
                                        </div>
                                        <div class="mv-command waiting">
                                          <span style="display:none" class="cmd-text">mkCopyPreq -W
        [WIN64_DRIVE]\[WIN64_DIR] -p [WIN_PREQ_DIR] -t
        [WIN64_DRIVE]\[WIN64_DIR]\[PreqDir] -d -o win_b64  -retry 10 -time 30
        -copyretry 10 -copytime 30</span>
                                          <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="CD_WS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                                          <span>W64_mkCopyPreq</span>
                                        </div>
                                      </div>
                                    </div>
                                    <div class="mv-thread">
                                      <table style="width:100%">
                                        <tbody>
                                          <tr>
                                            <td style="vertical-align: top;">
                                              <div>
                                                <div class="body"></div>
                                              </div>
                                            </td>
                                          </tr>
                                        </tbody>
                                      </table>
                                    </div>
                                  </div>
                                </div>
                              </td>
                            </tr>
                          </tbody>
                        </table>
                      </div>
                    </div>
                  </div>
                </td>
                <td style="vertical-align: top;">
                  <div>
                    <div class="body">
                      <div class="mv-thread">
                        <table style="width:100%">
                          <tbody>
                            <tr>
                              <td style="vertical-align: top;">
                                <div class="mv-command
            done">
                                  <div data-state="Done" data-start="2020-10-22_18-13-49" data-end="2020-10-22_18-14-53" data-profile="CD" data-system="WIN64" class="indicator mv-cmd-done"><a><span
        class="fonticon fonticon-check"></span></a></div>
                                  <span>WIN64_MCCMon</span>
                                </div>
                              </td>
                            </tr>
                          </tbody>
                        </table>
                      </div>
                    </div>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

这就是我想要的事情:


浏览器显示 SVG 并动态创建它们的能力在这种情况下会派上用场。这样你就不必手动将这些行硬编码到 html 中 - 你只需告诉浏览器它应该连接哪个元素。

基本上你添加一个空的 HTML<svg>元素插入正文并确保它位于要连接的对象的背景中。这可以通过例如来完成将其 CSS z-index 属性设置为负值。

然后:

  • 找出要连接的两个对象的屏幕坐标
  • 创建一个 svg<path>元素,用直线/曲线连接两个坐标
  • 将该路径附加到 svg

不过,这个解决方案的困难部分是获取实际的对象!如果我们仔细查看您的 html,我们会发现您将对象的所有标签都放在里面<span>元素。这很棒,因为我们可以简单地使用

document.getElementsByTagName("span")

得到一个HTML集合您网站上的所有 span 元素。如果我们现在更进一步,检查.innerText该集合内元素的属性并将其与对象的文本之一进行比较,例如W_SCMadl_刷新我们可以获得对实际对象的引用。不幸的是,我们对 span 元素本身并不真正感兴趣,因为您想要将这些行与其父级的子 DIV 之一连接起来。

让我们检查一下这些子元素。我们可以看到这些都是 DIV,其 CSS 类为指示器 mv-cmd-done, 指标 mv-cmd-aborted, ...

因此,要实际获取这些元素之一,我们需要搜索父容器子容器的 classNames 是否存在字符串指示符,例如:

element.className.indexOf("indicator") != -1

层次结构中唯一没有此类元素的元素是最顶层命令序列启动- 所以我们需要包括一个例外。

所有内容放在一起看起来有点像这样(只需单击“运行代码片段”):

let paths = document.getElementById("paths");
let connections2 = [];

function getElement(element) {
  for (let a = 0; a < element.length; a++) {
    if (element[a].className.indexOf("indicator") != -1) {
      return element[a];
    }
  }

  return null;
}

function connectElements(connections) {
  let spans = document.getElementsByTagName("span");
  let start;
  let end;
  let temp;
  for (let a = 0; a < connections.length; a += 2) {
    for (let b = 0; b < spans.length; b++) {
      if (spans[b].innerText == connections[a]) {
        start = getElement(spans[b].parentElement.children);
      }
      if (spans[b].innerText == connections[a + 1]) {
        if (connections[a + 1] == "Command Sequence Starting") {
          end = spans[b];
        } else {
          end = getElement(spans[b].parentElement.children);
        }
      }
    }
    connections2.push({
      start: start,
      end: end
    });
  }
  coordinates();
}

function coordinates() {
  let padding = 5;
  let bezierWeight = 0.5;
  let oldPaths = paths.children;
  for (let a = oldPaths.length - 1; a >= 0; a--) {
    paths.removeChild(oldPaths[a]);
  }

  let x1, y1, x4, y4, dx, x2, x3, path, start, end;

  for (let a = 0; a < connections2.length; a++) {
    start = $(connections2[a].start);
    end = $(connections2[a].end);

    x1 = start.offset().left + start.width() / 2 - padding;
    y1 = start.offset().top + start.height() / 2 - padding;
    x4 = end.offset().left + start.width() / 2 - padding;
    y4 = end.offset().top + start.height() / 2 - padding;
    dx = Math.abs(x4 - x1) * bezierWeight;

    if (x4 < x1) {
      x2 = x1 - dx;
      x3 = x4 + dx;
    } else {
      x2 = x1 + dx;
      x3 = x4 - dx;
    }

    data = `M${x1} ${y1} C ${x2} ${y1} ${x3} ${y4} ${x4} ${y4}`;

    path = document.createElementNS("http://www.w3.org/2000/svg", "path");
    path.setAttribute("d", data);
    path.setAttribute("class", "path");
    paths.appendChild(path);
  }
}

connectElements(["W_SCMadl_refresh", "Command Sequence Starting", "WIN64_MCCMon", "Command Sequence Starting", "W64_mkCopyPreq", "WIN64_MCCMon"]);
#paths {
  z-index: -1;
  position: absolute;
}

.path {
  fill: none;
  stroke: #3ed21b;
  stroke-width: 6;
}

.mv-thread,
.mv-sequence {
  display: inline-block;
}

.mv-sequence,
.mv-subsequence {
  border: solid 1px #e0e0e0;
  border-radius: 15px;
  margin: 85px;
  padding: 10px;
  text-align: center;
}

.mv-sequence>.title,
.mv-subsequence>.title {
  font-size: 17px;
  background-color: cadetblue;
  border-radius: 7px 0px;
  color: #fff;
  font-weight: bold;
  padding: 10px;
}

.mv-sequence>.body,
.mv-subsequence>.body {
  min-width: max-content;
  display: inline-block;
  text-align: left;
}

.mv-command>div.indicator {
  display: inline-block;
  width: 32px;
  height: 32px;
  line-height: 32px;
  border-radius: 32px;
  text-align: center;
  font-size: 17px;
}

.mv-command>span {
  font-size: 13px;
  font-weight: bold;
}

.mv-command:before {
  content: "";
  background-color: #000;
  width: 3px;
  height: 16px;
  display: block;
  margin-left: 14px;
}


/* for done*/

.mv-command.done:before {
  background: #477738;
}

.mv-cmd-done {
  background: #57b847;
}

.mv-cmd-done>a>span,
.mv-command.done>span {
  color: #477738;
}


/* for aborted*/

.mv-command.aborted:before {
  background: #844138;
}

.mv-cmd-aborted {
  background: #ea4f37;
}

.mv-cmd-aborted>a>span,
.mv-command.aborted>span {
  color: #844138;
}


/* for waiting*/

.mv-command.waiting:before {
  background-color: #808080;
}

.mv-cmd-waiting {
  background: #f1f1f1;
}

.mv-cmd-waiting>span,
.mv-command.waiting>span {
  color: #808080;
}


/* for disabled*/

.mv-command.disabled:before {
  background: #80808080;
}

.mv-cmd-disabled {
  border: 1px solid #80808080;
}

.mv-cmd-disabled>span,
.mv-command.disabled>span {
  color: #80808080;
}


/* for running */

.mv-command.running:before {
  background: #005686;
}

.mv-cmd-running {
  border: 1px solid #005686;
}

.mv-cmd-running>a>span {
  color: #80808080;
  animation: mymove 2s infinite;
}

@keyframes mymove {
  from {
    color: #fff;
  }
  to {
    color: #368ec4;
  }
}

.mv-command.running>span {
  color: #80808080;
  animation: mymove 2s infinite;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<svg height="1000" width="1000" id="paths">
</svg>
<div>
  <div class="mv-sequence">
    <div class="body">
      <div class="mv-thread">
        <table style="width:100%">
          <span class="mv-sequence" style="background-color: green; color: aliceblue;">Command Sequence Starting</span>
          <tbody>
            <tr>
              <td style="vertical-align: top;">
                <div>
                  <div class="body">
                    <div>
                      <div class="body">
                        <div class="mv-command done">
                          <span style="display:none" class="cmd-text">[ScmRefresh]</span>
                          <div data-state="Done" data-start="2020-10-22_18-13-49" data-end="2020-10-22_18-14-40" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_SCMadl_refresh.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                          <span>W_SCMadl_refresh</span>
                        </div>
                        <div class="mv-command done">
                          <span style="display:none" class="cmd-text">adl_photo</span>
                          <div data-state="Done" data-start="2020-10-22_18-14-40" data-end="2020-10-22_18-14-41" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_adl_photo.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                          <span>W_adl_photo</span>
                        </div>
                        <div class="mv-command done">
                          <span style="display:none" class="cmd-text">code:[ScmCollect]
        -cr_later</span>
                          <div data-state="Done" data-start="2020-10-22_18-14-42" data-end="2020-10-22_18-14-43" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_adl_collect.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                          <span>W_adl_collect</span>
                        </div>
                        <div class="mv-command done">
                          <span style="display:none" class="cmd-text">adl_collect_cr</span>
                          <div data-state="Done" data-start="2020-10-22_18-14-43" data-end="2020-10-22_18-14-44" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-done"><a href="Main/MainThread/Release/Windows_SCM/W_adl_collect_cr.xml"><span
        class="fonticon fonticon-check"></span></a></div>
                          <span>W_adl_collect_cr</span>
                        </div>
                        <div>
                          <div class="body">
                            <div class="mv-command aborted">
                              <span style="display:none" class="cmd-text">[ScmSync]</span>
                              <div data-state="Aborted" data-start="2020-10-22_18-14-44" data-end="2020-10-22_18-14-54" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator mv-cmd-aborted"><a href="Main/MainThread/Release/Windows_SCM/Windows_SCM_sync/W_adl_sync.xml"><span
        class="fonticon fonticon-wrong"></span></a></div>
                              <span>W_adl_sync</span>
                            </div>
                            <div class="mv-command waiting">
                              <span style="display:none" class="cmd-text">[ScmAttach]
        -attached_fw_mod</span>
                              <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                              <span>W_adl_attach</span>
                            </div>
                          </div>
                        </div>
                        <div class="mv-command waiting">
                          <span style="display:none" class="cmd-text">adl_publish</span>
                          <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                          <span>W_adl_publish</span>
                        </div>
                        <div class="mv-command waiting">
                          <span style="display:none" class="cmd-text">code:[ScmDsWs]
        [workspace]</span>
                          <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="ChgWS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                          <span>W_adl_ds_ws</span>
                        </div>
                      </div>
                    </div>
                    <div class="mv-thread">
                      <table style="width:100%">
                        <tbody>
                          <tr>
                            <td style="vertical-align: top;">
                              <div>
                                <div class="body">
                                  <div>
                                    <div class="body">
                                      <div class="mv-command waiting">
                                        <span style="display:none" class="cmd-text">if not exist
        [WIN64_DRIVE]\[WIN64_DIR]\[PreqDir] mkdir
        [WIN64_DRIVE]\[WIN64_DIR]\[PreqDir]</span>
                                        <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="TCK" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                                        <span>W64_Shared_Preq_mkdir</span>
                                      </div>
                                      <div class="mv-command waiting">
                                        <span style="display:none" class="cmd-text">mkCopyPreq -W
        [WIN64_DRIVE]\[WIN64_DIR] -p [WIN_PREQ_DIR] -t
        [WIN64_DRIVE]\[WIN64_DIR]\[PreqDir] -d -o win_b64  -retry 10 -time 30
        -copyretry 10 -copytime 30</span>
                                        <div data-state="Waiting" data-start="-1" data-end="-1" data-profile="CD_WS_64b_Win" data-system="WIN64" class="indicator
        mv-cmd-waiting"><span class="fonticon fonticon-clock"></span></div>
                                        <span>W64_mkCopyPreq</span>
                                      </div>
                                    </div>
                                  </div>
                                  <div class="mv-thread">
                                    <table style="width:100%">
                                      <tbody>
                                        <tr>
                                          <td style="vertical-align: top;">
                                            <div>
                                              <div class="body"></div>
                                            </div>
                                          </td>
                                        </tr>
                                      </tbody>
                                    </table>
                                  </div>
                                </div>
                              </div>
                            </td>
                          </tr>
                        </tbody>
                      </table>
                    </div>
                  </div>
                </div>
              </td>
              <td style="vertical-align: top;">
                <div>
                  <div class="body">
                    <div class="mv-thread">
                      <table style="width:100%">
                        <tbody>
                          <tr>
                            <td style="vertical-align: top;">
                              <div class="mv-command
            done">
                                <div data-state="Done" data-start="2020-10-22_18-13-49" data-end="2020-10-22_18-14-53" data-profile="CD" data-system="WIN64" class="indicator mv-cmd-done"><a><span
        class="fonticon fonticon-check"></span></a></div>
                                <span>WIN64_MCCMon</span>
                              </div>
                            </td>
                          </tr>
                        </tbody>
                      </table>
                    </div>
                  </div>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>

正如你所看到的,有一个简单而方便的方法connectElements()函数接受字符串数组作为参数。该字符串是您要连接的对象的文本标签。例如W_SCMadl_刷新 and 命令序列启动

connectElements(["W_SCMadl_refresh", "Command Sequence Starting"]);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何制作一条曲线来连接 HTML 和 CSS 中的两个节点? 的相关文章