从div到div绘制弯曲的SVG箭头线 [英] Drawing curved SVG arrow lines from div to div

查看:377
本文介绍了从div到div绘制弯曲的SVG箭头线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用SVG绘制两条弯曲的箭头线来连接两个元素,以指示它们来回移动,就像这样:

I want to draw two curved arrow lines using SVG to connect two elements to indicate they go back and forth, like this:

我已经阅读了一些有关SVG的内容,但是我不确定如何创建垂直线.

I've read a bit about SVG but I'm not totally sure how to create a line that's vertical.

第二,如果SVG获取坐标,在创建SVG图形之前,我是否必须找到元素的坐标位置?如果调整了窗口大小,是否必须重新绘制?

Second, if SVG takes coordinates, do I have to find the coordinate position of the elements before creating the SVG drawing? Does it have to be re-drawn if the window size is adjusted?

推荐答案

制作一个svg元素,该元素(无形地)是整个文档的基础.这将同时按住两个箭头.插入两个svg path元素(箭头),其开始和结束坐标是根据要连接的div的位置计算的,其曲线是根据这些开始和结束坐标以所需的方式创建的.

Make an svg element that (invisibly) underlies the entire document. This will hold both arrows. Insert two svg path elements (the arrows) whose start and end coordinates are calculated based on the positions of the div's to be connected, and whose curve is created in whatever way you want based on those start and end coordinates.

对于以下示例,单击运行代码段".然后单击并拖动任一div,以查看如何动态创建箭头,即箭头随div一起移动.在代码片段中使用jQuery和jQueryUI只是为了使div易于拖动,而与箭头的创建和使用无关.

For the example below, click on "Run code snippet". Then click and drag either of the div's to see how the arrows are dynamically created, i.e. they move with the divs. jQuery and jQueryUI are used in the code snippet simply to allow the easy draggability of the divs and have nothing to do with the creation and use of the arrows.

此示例有两个箭头,分别从div边的中间开始和结束.当然,曲线的细节取决于您.使用svg pathd属性构造箭头线.在此示例中,"M"是路径将开始的"moveTo"坐标,而"C"点是三次贝塞尔曲线的第一和第二控制点以及最终坐标.您必须查找这些对象才能了解它们的含义. ,但这是在svg元素中创建平滑曲线的一般方法.箭头是使用svg <marker>元素添加的,您可以在此处阅读有关内容.

This example has two arrows starting and ending at the middle of the divs' sides. The details of the curve are, of course, up to you. The arrow lines are constructed using the d attribute of the svg path. In this example, "M" is the "moveTo" coordinates where the path will start and the "C" points are the first and second control points and final coordinate for a cubic bezier curve. You'll have to look those up to understand what they are, but they are a general way of creating smooth curves in an svg element. The arrowheads are added using an svg <marker> element which you can read about here.

更复杂的文档将需要更加仔细地确定svg path元素的开始和结束坐标,即箭头,但是此示例至少为您提供了一个开始的地方.

A more complex document would need more care to determine the start and end coordinates of the svg path elements, i.e. the arrows, but this example at least gives you a place to begin.

回答您的特定问题:

  • 如果SVG获取坐标,在创建SVG工程图之前我是否必须找到元素的坐标位置?是的,就像我在代码中所做的一样.

  • If SVG takes coordinates, do I have to find the coordinate position of the elements before creating the SVG drawing? Yes, as I've done in my code.

如果调整了窗口大小,是否必须重新绘制?可能是,取决于调整窗口大小时div自身发生的情况.

Does it have to be re-drawn if the window size is adjusted? Probably yes, depending on what happens to the divs themselves when the window is resized.

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>

这篇关于从div到div绘制弯曲的SVG箭头线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆