在两个 div 之间画一个箭头。

52

我正在寻找一个解决方案,但我原以为已经有人解决了这个问题。 但我看到的只有一些带有许多功能但没有简单解决方案的大项目。

实际上,我需要像这样的东西:

http://i.imgur.com/iktvmLK.png

所以我需要在包含若干正方形(divs)的 div 上绘制箭头。

<div id="container">
<div class="white_field"></div>
<div id="1" class="black_field">
<br style="clear:both;">    
<div id="2" class="black_field">
<div class="white_field"></div>
<br style="clear:both;">    
<div id="3" class="black_field">
<div class="white_field"></div>
</div>

我朝画布的方向看去,但是在我的div后面并没有看到画布(或许加一些z-index会有帮助)。 但仍然很奇怪,我找不到一个现成的解决方案来解决这个看起来经常出现的问题。(为了在网站上解释某些东西,箭头几乎是必须的)


箭头线条需要如何表现:延长、旋转等。 - markE
“在网站上解释某些事情,箭头几乎是必不可少的” - 是的,这个问题早就被解决了。传统的解决方案是使用 gif(或多个 gif 或 png)。现在,如果你想使用像 svg 或 canvas 这样的新技术,那么这是一个新的问题,人们还没有动力去解决,因为他们只需要让他们的艺术家为他们生成 gif。 - slebetman
7个回答

54

你可能考虑使用SVG。

图片描述

特别是,你可以使用带有箭头路径形状的标记结束的线。

确保设置orient = auto,以使箭头末端旋转以匹配线的斜率。

由于SVG是DOM元素,因此您可以在javascript中控制线的起始/结束位置。

这里是代码和一个Fiddle:http://jsfiddle.net/m1erickson/9aCsJ/

<svg width="300" height="100">

    <defs>
        <marker id="arrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
            <path d="M2,2 L2,11 L10,6 L2,2" style="fill:red;" />
        </marker>
    </defs>

    <path d="M30,150 L100,50"
          style="stroke:red; stroke-width: 1.25px; fill: none;
                 marker-end: url(#arrow);"
    />

</svg>

8
我有点困惑:我没有看到关于连接两个元素的内容。我是漏看了什么,还是说这个想法是我自己推测元素的位置?请帮我理一下思路。 - David Roundy
2
@DavidRoundy。确切地说,这个问题是关于连接器而不是查找div。但由于每个div都有一个#id,所以您可以使用[getComputedStyle](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)来查找其位置和大小。干杯! :-) - markE
你如何改变箭头的宽度?我找不到造成这种效果的部分 :s - tugberk
1
@tugberk 只需将stroke-width设置为路径样式即可。因为标记使用markerUnits="strokeWidth"作为默认值,所以箭头可能会变得太大。但是,使用transform:scale()很容易进行调整。http://jsfiddle.net/9aCsJ/1007/ - Timo Kähkönen
我知道现在有点晚了,但我修改了@markE的代码片段,创建了一个箭头,可以在已经存在的元素和新创建的元素之间创建,距离不超过1000px(可以自定义),而不会影响原始元素的位置。我还没有足够的时间来测试它是否会影响周围的其他元素,但稍后我会继续研究。我正在使用Casper创建模板,所以我认为这可能很有用。https://jsfiddle.net/Cody0913/yggrkb15/3/ - Cody Fidler
更新我的上一个评论,在背景中添加了一个span来代替被指向的元素,并且定位是在函数调用中确定的。https://jsfiddle.net/Cody0913/yggrkb15/6/ 希望这能帮助需要的人。 - Cody Fidler

26

是的,非常适合这个目的。可惜它不能直接在create-react-app中使用(https://github.com/anseki/leader-line/issues/12)。 - superjos
很抱歉听到这个,@superjos。我的使用方式是创建一个完美无缺的简单静态页面。 - Jerome Provensal
问题更多的是你喜欢画一个小箭头,而为此需要加载98 KB... - Avatar

11

我不知道是否还有人会关注这个帖子,但是这是我使用的解决方案,与 @markE 的答案仅略有不同,因为这个答案使得指定行的起始和结束位置更加容易。

<head>
  <style>
    .arrow{
      stroke:rgb(0,0,0);
      stroke-width:2; 
      marker-end:url(#markerArrow)
    }
  </style>
</head>

<body>
  <svg height="210" width="500">
    <defs>
        <marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6"
               orient="auto">
            <path d="M2,2 L2,11 L10,6 L2,2" style="fill: #000000;" />
        </marker>
    </defs>
    
    <line x1="0" y1="0" x2="200" y2="100" class="arrow" />
  </svg>

</body>

你所需要做的就是改变这条线的 x 和 y 坐标!我在我的 React 应用程序中使用了这个答案,效果非常好。 这里是示例

.arrow {
  stroke: rgb(0, 0, 0);
  stroke-width: 2;
  marker-end: url(#markerArrow)
}
<svg height="210" width="500">
  <defs>
    <marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">
      <path d="M2,2 L2,11 L10,6 L2,2" style="fill: #000000;" />
    </marker>
  </defs>
  <line x1="0" y1="0" x2="200" y2="100" class="arrow" />
</svg>


这里有一个笔,展示了如何修改箭头的起点/终点 https://codepen.io/jdhenckel/pen/NWWrXqr - John Henckel
谢谢...但我有点强迫症,你的箭头歪了,参考点在箭头中间(而不是在箭头尖上)。;-) - ashleedawg

3

除非你想编写和调试像这样的东西:https://dev59.com/6XRB5IYBdhLWcg3wro2B#623770,否则请仅返回翻译后的文本。 - c69
1
JSPlumb是我在问题"But I saw only big projects with a lot of features but no simple solution."中所指的。 - Alexander P
28
好的,它只需要3500美元。 - shrewmouse
我在神奇的Python Tutor网站上看到了jsPlumb的实际应用,所以它可能值得一试(尚未实际尝试)。它是开源的,可在MIT许可下使用。(除非您需要它,否则请忽略网站上的“升级销售”) - ShreevatsaR

1
我建议使用这个:
https://www.cssscript.com/connect-elements-directional-arrow/
非常简单易用 :)

然后你可以这样做:

<connection from="#id_1" to="#id_2" color="red" tail></connection>

如何包含它:

将.zip文件解压缩到您的项目文件夹中。 要么复制CSS和JavaScript到您的项目中,要么在您的项目中添加对这些文件的引用:

<head>
        <!-- Your head-codes here -->
        <link rel  = "stylesheet" type = "text/css" href = "../plugins/domarrow.js-master/domarrow.css"/>
</head>
<body>
    <!-- Your body-codes here -->
    <script src="../plugins/domarrow.js-master/domarrow.js"></script>
</body>

在我的情况下,文件结构是:

C/MyProject/:.
│
├───css
│       start.css
│
├───html
│       start.html <--- write here
│
├───js
│       start.js
│
└───plugins
    │
    └───domarrow.js-master
            domarrow.css
            domarrow.js

这就是为什么我需要在相对路径的开头加上 "../",它的意思是“向外跳出一层”,例如:"../plugins" 就会从 "html" 文件夹中跳出并进入 "plugins" 文件夹。
根据你的文件布局调整文件路径。

GitHub上的库:https://github.com/schaumb/domarrow.js - Avatar

0

Canvas和jCanvas

根据您的需求,您一定要检查使用Canvas和jCanvas库。它使这样的事情变得轻而易举。

我曾经尝试使用DIV和jQuery来做所有的事情,但总是缺乏交互性和质量。这真的打开了大门,而不增加代码复杂性。

希望这能帮助像我一样的其他人。

JP

编辑 2017年5月20日:

我曾经在这里放了一个示例,链接到jCanvas的沙盒,其中包含绘制两个元素之间箭头并拖动这两个元素的所有代码所需的代码。然而,该链接不再有效,我也没有将代码放在其他地方。

因此,我仍然认为您应该检查jCanvas,但不幸的是,我没有任何示例代码可以为您提供起点。


4
@Shrewmouse 哦不,看起来沙盒已经被移除了。我猜这就是为什么他们建议将代码放在答案本身中以便保存的原因。该死。我会更新答案的。 - Joshua Pinter

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接