javascript - 从 div 到 div 绘制 flex 的 SVG 箭头线

标签 javascript html css dom svg

我想使用 SVG 绘制两条 flex 的箭头线来连接两个元素以指示它们来回移动,如下所示:

enter image description here

我读过一些关于 SVG 的内容,但我不太确定如何创建垂直线。

其次,如果SVG是取坐标的,在创建SVG绘图之前是否必须先找到元素的坐标位置?调整窗口大小是否需要重新绘制?

最佳答案

制作一个svg (无形地)构成整个文档基础的元素。这将容纳两个箭头。插入两个 svg path元素(箭头),其开始和结束坐标是根据要连接的 div 的位置计算的,其曲线是根据这些开始和结束坐标以您想要的任何方式创建的。

对于下面的示例,单击“运行代码片段”。然后单击并拖动其中一个 div 以查看箭头是如何动态创建的,即它们与 div 一起移动。代码片段中使用 jQuery 和 jQueryUI 只是为了让 div 易于拖动,与箭头的创建和使用无关。

这个例子有两个箭头,开始和结束在 div 边的中间。当然,曲线的细节由您决定。箭头线是使用 d 构建的svg 的属性 path .在此示例中,“M”是路径开始的“moveTo”坐标,“C”点是三次贝塞尔曲线的第一个和第二个控制点和最终坐标。你必须 look those up了解它们是什么,但它们是在 svg 元素中创建平滑曲线的一般方法。使用 svg <marker> 添加箭头您可以阅读有关 here 的元素.

一个更复杂的文档需要更加小心地确定 svg 的开始和结束坐标 path元素,即箭头,但这个例子至少给了你一个开始的地方。

具体问题的答案:

  • 如果 SVG 采用坐标,我是否必须在创建 SVG 绘图之前找到元素的坐标位置?是的,正如我在代码中所做的那样。

  • 调整窗口大小是否需要重新绘制?可能是的,这取决于调整窗口大小时 div 本身发生了什么。

var divA       = document.querySelector("#a");
var divB       = document.querySelector("#b");
var arrowLeft  = document.querySelector("#arrowLeft");
var arrowRight = document.querySelector("#arrowRight");

var drawConnector = function() {
  var posnALeft = {
    x: divA.offsetLeft - 8,
    y: divA.offsetTop  + divA.offsetHeight / 2
  };
  var posnARight = {
    x: divA.offsetLeft + divA.offsetWidth + 8,
    y: divA.offsetTop  + divA.offsetHeight / 2    
  };
  var posnBLeft = {
    x: divB.offsetLeft - 8,
    y: divB.offsetTop  + divB.offsetHeight / 2
  };
  var posnBRight = {
    x: divB.offsetLeft + divB.offsetWidth + 8,
    y: divB.offsetTop  + divB.offsetHeight / 2
  };
  var dStrLeft =
      "M" +
      (posnALeft.x      ) + "," + (posnALeft.y) + " " +
      "C" +
      (posnALeft.x - 100) + "," + (posnALeft.y) + " " +
      (posnBLeft.x - 100) + "," + (posnBLeft.y) + " " +
      (posnBLeft.x      ) + "," + (posnBLeft.y);
  arrowLeft.setAttribute("d", dStrLeft);
  var dStrRight =
      "M" +
      (posnBRight.x      ) + "," + (posnBRight.y) + " " +
      "C" +
      (posnBRight.x + 100) + "," + (posnBRight.y) + " " +
      (posnARight.x + 100) + "," + (posnARight.y) + " " +
      (posnARight.x      ) + "," + (posnARight.y);
  arrowRight.setAttribute("d", dStrRight);
};

$("#a, #b").draggable({
  drag: function(event, ui) {
    drawConnector();
  }
});

setTimeout(drawConnector, 250);
/* The setTimeout delay here is only required to prevent
 * the initial appearance of the arrows from being
 * incorrect due to the animated expansion of the
 * Stack Overflow code snippet results after clicking
 * "Run Code Snippet." If this was a simpler website,
 * a simple command, i.e. `drawConnector();` would suffice.
 */
html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}
#instructions {
  position: fixed;
  left: 50%;
}
#a, #b {
  color: white;
  text-align: center;
  padding: 10px;
  position: fixed;
  width: 100px;
  height: 20px;
  left: 100px;
}
#a {
  background-color: blue;
  top: 20px;
}
#b {
  background-color: red;
  top: 150px;
}
<p id="instructions">Click and drag either div to see automatic arrow adjustments.</p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <defs>
    <marker id="arrowhead" viewBox="0 0 10 10" refX="3" refY="5"
        markerWidth="6" markerHeight="6" orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" />
    </marker>
  </defs>
  <g fill="none" stroke="black" stroke-width="2" marker-end="url(#arrowhead)">
    <path id="arrowLeft"/>
    <path id="arrowRight"/>
  </g>
</svg>
<div id="a">Div 1</div>
<div id="b">Div 2</div>

关于javascript - 从 div 到 div 绘制 flex 的 SVG 箭头线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39553105/

相关文章:

javascript - 如果已经预先设置了一个属性,如何防止再次设置该属性?

html - 如何优化包含大量图像的超长页面?

html - 媒体查询未设置正确的屏幕分辨率

javascript - CKeditor,将标签名称传递给插件中的 addcommand

html - 由 div 创建的表上的列宽相等

jQuery html 属性在 IE 中不起作用

html - 将嵌套表格定位到单元格的右侧

javascript - http.IncomingMessage实现nodejs有哪些事件

javascript - 提交表单后刷新页面

javascript - 尝试使用锐利的 Node.js 调整流图像的大小