33

How can we draw a line in html page. I tried using canvas but found that its not working. Maybe browser doesn't support it. Can there be other easier way.

sam
  • 349
  • 1
  • 3
  • 5

10 Answers10

65

EDIT: Maybe it is little bit late but here is my new implementation. Hope it's more readable.

function createLineElement(x, y, length, angle) {
    var line = document.createElement("div");
    var styles = 'border: 1px solid black; '
               + 'width: ' + length + 'px; '
               + 'height: 0px; '
               + '-moz-transform: rotate(' + angle + 'rad); '
               + '-webkit-transform: rotate(' + angle + 'rad); '
               + '-o-transform: rotate(' + angle + 'rad); '  
               + '-ms-transform: rotate(' + angle + 'rad); '  
               + 'position: absolute; '
               + 'top: ' + y + 'px; '
               + 'left: ' + x + 'px; ';
    line.setAttribute('style', styles);  
    return line;
}

function createLine(x1, y1, x2, y2) {
    var a = x1 - x2,
        b = y1 - y2,
        c = Math.sqrt(a * a + b * b);

    var sx = (x1 + x2) / 2,
        sy = (y1 + y2) / 2;

    var x = sx - c / 2,
        y = sy;

    var alpha = Math.PI - Math.atan2(-b, a);

    return createLineElement(x, y, c, alpha);
}

document.body.appendChild(createLine(100, 100, 200, 200));

Explanation (as they say "a picture is worth a thousand words"):

Draw line explanation sketch

madox2
  • 49,493
  • 17
  • 99
  • 99
  • 1
    all other answers are for vertical/horizontal lines only. this one is for lines with any degree. – oberhamsi Jul 20 '12 at 14:23
  • ^^Inaccurate. I do like this answer because it does it programmatically, however it's not the only answer to reference degrees. You can do degrees through CSS rotation of html divs that are essentially short and wide rectangles. – Metagrapher Jan 31 '13 at 19:33
  • 1
    @madox2, could you please add comments to your code to facilitate its readability and ease the burden on the user to reverse engineer your code? (particularly the "if(y1 < y2){" statement) – Metagrapher Jan 31 '13 at 19:36
  • This is a good code, when adding transform:rotate('+deg+'deg), works also on IE11. – jacouh Jun 17 '14 at 12:10
  • Congratulations @John. I still have to parse out this code, think about what each line is doing, and see how it's relevant and why what was done was done in order to grok it, every time I read it. It's not exactly universally immediately comprehensible, but thanks for your "mee too" vote providing your anecdotal evidence. – Metagrapher Oct 27 '14 at 18:29
  • I didn't think I was being an asshole until my comment to you @John. Sorry. It wasn't my intent up until your comment, which I simply felt I was responding in kind. It sounds like a misunderstanding. Which is coincidental or ironic? I get lost on the intricacies of that definition. I guess I get lost easily, which is why I like comments. – Metagrapher Oct 28 '14 at 18:17
  • @Metagrapher "Reverse engineering" is what you do when you try to understand binary code. Applying that phrase to source code is being an asshole to the one who wrote it. – John Oct 28 '14 at 20:36
  • 6
    reverse engineering has a much broader use than simply understanding binary code. One can quite reverse engineer a television set if you like. This comment thread is getting a bit pedantic, no? There's never going to be agreement or a winner, just two guys trying to have bigger balls on the internet. Let's just drop the animosity and back and forth, eh, @John? – Metagrapher Oct 28 '14 at 21:58
  • Thanks for this solution. However, I found that after creating the line using `document.createElement`, if the created element is later appended to some container, say using jQuery's `append()`, the positioning gets messed. Solution was to store the style in an attribute on the element, and later retrieve and apply it after performing the `append()`. – JWL Jun 22 '20 at 14:13
  • 1
    @Metagrapher agreed on dropping the animosity, but I don't read pedantism in John's objection to the word "reverse engineering", instead, I read that, to him, the words "reverse engineering" seemed like an overly harsh and insulting thing for someone to say about a piece of source code. It also seems clear that you didn't intend to be harsh or insulting, but sometimes words carry different connotations to different people. (It also seems clear that some comments were deleted, so if this whole thing isn't making enough sense any more, perhaps the whole thread could be deleted, including this) – Don Hatch Nov 24 '22 at 17:36
  • 1
    FWIW I give this answer an enthusiastic thumbs up, regardless of whether I grok the details of the specific transform math code used, simply because it shows me a nice technique for how to solve a problem like this-- getting some simple graphics into the html flow. Given that, I can figure out the details of the transforms on my own. – Don Hatch Nov 24 '22 at 17:41
  • @DonHatch it does look like some comments were deleted, you're right. And, I like your explanation of respective intents, that feels accurate to me. Thank you. I think I must've thought the definition was overly narrow and so thus pedantic, but it doesn't really matter in the end. You're right in that I did not intend insult to @ madox2. I might have phrased my request for comments better, though I LOVE his new explanation which is much more comprehensible than the original, especially with accompanying image for Pythagorean clarity. – Metagrapher Jul 16 '23 at 02:30
  • @DonHatch in case you didn't fully grok the math in the transform code, it's basically just getting line length with Pythagorean Theorem: `A**2 + B**2 = C**2` where C is the hypotenuse--the diagonal of the box created from X1,Y1 by X2,Y2--and is the line we're drawing. Often when we see division by 2 in a formula, we're finding the center, that's the case here for `sx`, `sy`. HTML finds positions based on left, top corner, then CSS rotates around the center point, thus the need to calculate the leftmost X with `x = sx - c / 2`. Finally atan2 finds the counterclockwise angle for the CSS rotate – Metagrapher Jul 16 '23 at 02:59
  • Ah, I see, the whole exchange here was about the version *before* the latest edit. – Don Hatch Jul 16 '23 at 04:33
  • @Metagrapher thanks for the explanation. Ok, I finally read the math code :-) Looks good, I suggest a couple of changes for simplicity (I don't want to just make an edit since the author might not agree). (1) change `Math.sqrt(a * a + b * b)` to `Math.hypot(a, b)`. (2) change `var alpha = Math.PI - Math.atan2(-b, a);` to `var alpha = Math.atan2(b, a); // clockwise rotation about center in radians` (yes, clockwise, not counterclockwise, I believe) (3) add `+ 'transform: rotate(' + angle + 'rad); '` (which is, I think, the modern way to spell it). – Don Hatch Jul 16 '23 at 04:49
10

you could define:

<div id="line1" class="line vertical"></div>
<div id="line2" class="line horizontal"></div>

.line {
  position: absolute;
  background-color: #000000;
}

.vertical { 
   width: 1px;
   height: 500px;
}

.horizontal {
   width: 500px;
   height: 1px;
}

#line1 {
   top: 20px;
   left: 50%;
}

#line2 {
   top: 260px;
   left: 25%;
}

/* for added rotation effects */
.forty-five {
   transform: rotate(45deg);
}

if you want to get into diagonal lines you could begin to try some rotation with transform: rotate(45deg); The IE Compatible method of rotating objects is discussed thoroughly here, which is terribly complicated. I do not know the IE compatible way to rotate divs, sorry., but that would work in Safari, Firefox, Chrome, and Opera.

[EDITS]

2014/11/08 - sjc - updated transform rules. Added MozDev links and IE rotation SO links.

Community
  • 1
  • 1
Metagrapher
  • 8,602
  • 1
  • 24
  • 31
  • also, you may not want to absolutely position the div. It depends on how you are using the line. If you are just doing a horizontal rule then there is actually a tag for that, too...
    – Metagrapher Nov 24 '10 at 19:13
6

i found myself needing a solution on this so i developped one using "hr" div and some gradient in border-image. Here is a Jsfiddle link to test it and the code below.

<html lang="fr">
<head>
<script>
    window.addEventListener("load",function(){
        function pow2(n){
            return n*n;
        }   

        var p1 = {
            id:"p1",
            x:150,
            y:50
        };
        var p2 = {
            id:"p2",
            x:300,
            y:250
        };
        var select = null;

        function getAngle(){

            var dist = Math.sqrt(pow2(p1.x-p2.x)+pow2(p1.y-p2.y));
            var l = document.getElementById("line");
            var cos = (p2.x-p1.x)/Math.sqrt(pow2(p2.x-p1.x)+pow2(p2.y-p1.y));
            var behind = p1.x < p2.x;
            var higher = p1.y > p2.y;
            l.style.width = (dist*2)+"px";
            l.style.left = (p1.x-dist)+"px";
            l.style.top = (p1.y)+"px";

            l.style.transform = "rotateZ("+(higher?-1:1)*Math.acos(cos)*(180/Math.PI)+"deg)";
        }

        var down = false

        document.addEventListener("mousemove",function(e){
            if(select){
                select.x = e.pageX;
                select.y = e.pageY;
                console.log(p1);
                var p = document.getElementById(select.id);
                p.style.left = (select.x-5)+"px";
                p.style.top = (select.y-5)+"px";
                getAngle();
            }
        });
        document.addEventListener("mouseup",function(e){
            if(!select)
                select = p1;
            else if(select == p1)
                select = p2;
            else 
                select = null;
        });
        document.addEventListener("mousedown",function(e){
            down = true;
        });
    });
</script>
</head>
<body>
<hr id="line" style="
position: absolute;
top: 50px;
left: -100px;
width: 500px;
margin: 0;
-webkit-transform: rotateZ(53.1deg);
border-width: 1px;      border-style: solid;                          
border-image: linear-gradient(to right, #ffffff 0%,#ffffff 49%,#000000 50%,#000000 100%) 1;
"/>
<div id="p1" style="
border-radius: 5px;
width: 10px;
background: #000;
position: absolute;
height: 10px;
top: 45px;
left: 145px;
"></div>
<div id="p2" style="
border-radius: 5px;
width: 10px;
background: #000;
position: absolute;
height: 10px;
top: 245px;
left: 295px;
"></div>
</body>
</html>

hope it helps someone :)

Insomniak Dev
  • 139
  • 2
  • 4
  • rotated
    with DOMelem.style.transform =rotateZ(angle) that's the good solution, are boring : no copy/paste, no really dynamic DOM into it, see http://robert.ocallahan.org/2011/11/drawing-dom-content-to-canvas.html why canvas must be avoided as possible
    – reuns Oct 17 '15 at 21:57
2

The <canvas> object is the easiest way (aside from plopping an image or using flash). Also, please post your code and tell us under what browser you're trying to use <canvas>. We can't tell you what you're doing wrong otherwise.

As far as support is concerned, from Wikipedia:

The element is currently supported by the latest versions of Mozilla Firefox, Google Chrome, Safari, and Opera. It is not natively implemented by Internet Explorer (IE) as of version 8[7], though support is in development for Internet Explorer 9; however, many of the Canvas element's features can be supported in IE, for example by using Google or Mozilla plugins, JavaScript libraries and either Adobe Flash or IE's proprietary VML.

SVG is another option, but (surprise!) IE doesn't it support it (IE9 is supposed to support some parts of it).

I'm also not sure what kind of line you want to draw. I mean, you could just make a div and only enable one of its borders - that would be a straight line.

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
2

Not all browsers support the <canvas/> element. Try a cross-browser solution, like FlashCanvas or excanvas.

The alternative is using SVG.

Klemen Slavič
  • 19,661
  • 3
  • 34
  • 43
0

Hi there i made a jQuery plugin for that propose. It is crossbrowser and don't use SVG or CANVAS. Check it: https://github.com/tbem/jquery.line

tbem
  • 595
  • 4
  • 14
0

I find that the < hr > tag works very well if all you want is a horizontal line accross the page.

0

options for cross browser vector graphics include Raphaël and svgweb

tim
  • 131
  • 3
0

maybe this package can help. You specify starting and ending point for line that you want to draw. https://www.npmjs.com/package/draw-line-connect

Burak Gündüz
  • 466
  • 5
  • 11
-3

I found this code on w3schools.com at https://www.w3schools.com/tags/canvas_lineto.asp

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(300,150);
ctx.stroke();

this allows you to easily draw lines on a canvas. Hope this helps!

Pete K.
  • 112
  • 3
  • 11
  • 1
    You can't just copy code from W3Schools. Their code is not under a Creative Commons license. See also my answer on Meta: https://meta.stackexchange.com/a/141240/188419 – Emil Vikström Apr 06 '17 at 08:56
  • Thus without considering you need a canvas object to use the code above. – Andrea Moro Jul 03 '19 at 20:20