52

I'm searching for a solution of the question that I expected to be solved already. But I saw only big projects with a lot of features but no simple solution.

Actually I need to get something like that:

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

So to get an arrow drawing over a div containing some squares (divs)

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

I looked in the canvas direction but stumbled on tha canvas was not visible behind my divs ( maybe some z-index should help ) But still strange that I couldn't find some ready-made solution of a problem that seems to me coming up often. ( to explain some thing on the site arrows are almost a must )

Liam
  • 27,717
  • 28
  • 128
  • 190
Alexander P
  • 775
  • 1
  • 9
  • 19
  • How do you need the arrowed line to behave: lengthen, rotate, etc. – markE Nov 17 '13 at 23:10
  • `to explain some thing on the site arrows are almost a must` - Yes, this was done and solved a long time ago. The traditional solution was to use a gif (or several gifs or pngs). Now, if you want to use newer tech like svg or canvas then that's a new problem that people haven't had motivation to solve yet because they simply ask their artist to generate gifs for them. – slebetman Nov 17 '13 at 23:20

7 Answers7

53

You might consider SVG.

enter image description here

In particular, you can use a line with a marker-end shaped with an arrow-path.

Be sure to set orient=auto so the arrowhead will be rotated to match the slope of the line.

Since SVG is a DOM element, you can control the start/end position of the line in javascript.

Here is code and a 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>
markE
  • 102,905
  • 11
  • 164
  • 176
  • 7
    I'm confused: I don't see anything here about connecting two elements. Am I missing something, or is the idea somehow that I may divine the location of the elements myself? – David Roundy Jul 06 '16 at 14:16
  • 2
    @DavidRoundy. Exactly, the question is about the connector rather than finding divs. But since each div has an #id so you can use [getComputedStyle](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to find its position and size. Cheers! :-) – markE Jul 06 '16 at 17:27
  • how can you change the width of the arrow? I was not able to find which part is making that effect :s – tugberk Jul 28 '16 at 09:46
  • 1
    @tugberk Just setting stroke-width to path style. Because marker uses markerUnits="strokeWidth" as a default, the arrow may become too large. But it is easy to adjust using transform:scale(). http://jsfiddle.net/9aCsJ/1007/ – Timo Kähkönen Aug 09 '16 at 01:16
  • I know that this is rather late, I modified @markE fiddle to create an arrow between an element that already exists and a created element within 1000px (can be defined) without affecting the position of the original element. Haven't had enough time to play around with it not affecting other elements around it, but will work more on it later. I'm creating templates with Casper, so I thought it might be useful. https://jsfiddle.net/Cody0913/yggrkb15/3/ – Cody Fidler Nov 02 '16 at 16:48
  • Update to my prev comment, added a span in background to take place of element being pointed at and positioning is determined in function call https://jsfiddle.net/Cody0913/yggrkb15/6/ I hope this helps anyone that needs this. – Cody Fidler Nov 02 '16 at 17:41
25

I highly recommended this library: https://anseki.github.io/leader-line/

It's pretty powerful, fast, super easy to use and it worked flawlessly for me.

enter image description here

Jerome Provensal
  • 931
  • 11
  • 22
  • yes, quite fit for the purpose. Sadly it does not work out-of-the-box with create-react-app (https://github.com/anseki/leader-line/issues/12) – superjos Jan 05 '22 at 12:21
  • Sorry to hear that @superjos. My usage was to create a simple static page that worked flawlessly. – Jerome Provensal Jan 14 '22 at 02:54
  • The issue is more that you like to draw a little arrow and you need to load 98 KB for that purpose... – Avatar Oct 25 '22 at 10:44
11

I have no idea whether anybody looks at this thread anymore but here's the solution i used, it differs only slightly from @markE answer in that this answer makes it much easier to specify exactly where the line needs to start and stop.

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

All you have to do is change the x and y coordinates of the line! I used this answer in my react app and it worked beautifully. And heres the fiddle.

.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>
ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Red
  • 140
  • 1
  • 7
  • Here is a pen that shows how to modify the arrow start/end https://codepen.io/jdhenckel/pen/NWWrXqr – John Henckel Oct 16 '19 at 15:32
  • Thanks... but I'm a little OCD and your arrowhead is lop-sided and the reference point is in the middle of the arrowhead (instead of at the tip of the arrow). ;-) – ashleedawg Jul 07 '20 at 00:18
3

Use a library, like JSPlumb: https://jsplumbtoolkit.com/

Brad
  • 159,648
  • 54
  • 349
  • 530
c69
  • 19,951
  • 7
  • 52
  • 82
  • unless you want to write and debug something like THIS: http://stackoverflow.com/a/623770/946789 – c69 Nov 18 '13 at 00:01
  • 1
    JSPlumb is what I meant in the question "But I saw only big projects with a lot of features but no simple solution." – Alexander P Nov 19 '13 at 16:56
  • 28
    Yeah, it's only $3500 – shrewmouse Sep 01 '17 at 15:47
  • I've seen jsPlumb in action on the fantastic [Python Tutor](http://www.pythontutor.com/visualize.html#mode=edit) site, so it may be worth a try (haven't actually tried it yet). It is open-source, available under the MIT license. (Ignore the “upselling” on the website unless you need it.) – ShreevatsaR Feb 09 '19 at 14:05
1

I recommend using this:
https://www.cssscript.com/connect-elements-directional-arrow/
Very simple to use :)

You can do this then:

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

How to include it:

You extract the .zip file to your projects folder. Either copy over the CSS & JavaScript to your project, or add a reference to those files in your project:

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

In my case the file structure is:

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

That's why I need the "../" in the beginning of the relative path, it means "step out one level", so for example: "../plugins" exits the "html" folders & goes into the "plugins" folder instead.

Adjust the file-path according to your file layouts.

Sebastian Norr
  • 7,686
  • 2
  • 12
  • 17
0

Its fairly simple to create the arrow head. See this example on CSS Tricks. Maybe using this inside a container which has the arrow line might do it.

0

Canvas and jCanvas

Based on your needs, you should definitely check out using Canvas and the jCanvas library. It makes things like this a breeze.

I ventured down the road of doing everything with DIVs and jQuery but it always fell short on interactivity and quality. This really kicks open the doors without adding code complexity.

Hope that helps others, like me.

JP

EDIT 2017 05 20:

I used to have an example here that linked to the jCanvas' sandbox with all the code you needed to draw an arrow between two elements and drag both of those elements around the canvas. However, that link no longer works and I don't have the code anywhere else.

So, I still think you should check out jCanvas but unfortunately I don't have any sample code to start you off.

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • 4
    @Shrewmouse Oh no, it appears the sandbox has been removed. I guess that's why they suggest putting the code in the answer itself so it's preserved. Damn. Will update the answer. – Joshua Pinter May 20 '17 at 15:44