Drawing Lines with CSS3

One of the requirements for my game Lexil were lines that connected the letters in each word. At first I thought of using the canvas, however it turns out that drawing lines with CSS3's css transforms is quite simple, and has some nice benefits as well.

Let's dive in and learn how you can use CSS transforms to draw a line between two points. Of course if you're impatient you can just skip to the demo.

CSS Transforms

CSS transforms let you perform affine transformations on DOM elements. These include scaling, rotating, and skewing an element.

For instance, if you want to display a photo at a jaunty angle you could transform it with the following CSS:

Transform
Transforming an Image
img.jaunty-photo{
  transform: rotate(10deg);
}

The properties of an element's transform are the functions you want to apply (scale, rotate, skew, etc). With this simple concept in place you're half way to drawing your lines.

CSS Origin

By default transforms are applied assuming the origin is at the center, however when drawing lines you probably want to draw from one point to another, not expanding out from the center. This is where the transform-origin comes into play. If you wanted to rotate an element around it's top left corner, you could set the transform-origin as follows:

Transform Origin
Transform Origins
div.transforming-on-corner{
  transform-origin: 0% 0%;
}

The properties of transform-origin are the x and y position of the origin. In the example above, the origin is 0% to the right and 0% down, so the top left corner.

A Geometry Refresher

Now for a quick bit of geometry, assuming we know the two points we want to draw a line between, all we need now is to figure out the angle to draw the line at, and the length of the line we want. The length is easy, it's just the distance function, and the angle can be derived from the arc tangent of the x and y components of the line. You'll probably be using JavaScript for this bit:

// Assuming points are (x1,y1) and (x2,y2)
var length = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
var angle  = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;

Notice that the angle is converted from radians to degrees with the 180 / Math.PI, this is so we can plug it into the CSS later.

Putting It All Together

We have all the pieces in place to draw lines now.

  1. The tranform-origin is 0 50% so that the line rotates around center of its first point.
  2. The angle computed above is the transform.
  3. The height of the element is the line width.
  4. The width of the element is the length computed above.

So your line's CSS will look something like this:

div.line{
  transform-origin: 0 100%;
  height: 3px; /* Line width of 3 */
  background: #000; /* Black fill */
}

Then, assuming you are using jQuery, the javascript to add your line to the DOM looks like this:

function createLine(x1,y1, x2,y2){
    var length = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
  var angle  = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
  var transform = 'rotate('+angle+'deg)';

    var line = $('<div>')
        .appendTo('#page')
        .addClass('line')
        .css({
          'position': 'absolute',
          'transform': transform
        })
        .width(length)
        .offset({left: x1, top: y1});

    return line;
}

That's it, not you can put lines where ever you want.

And One More Thing

Since these lines are just DOM elements you can attach event listeners to them, style them with css, and use use CSS Transitions to animate them. This gives you some of the useful features of SVG, but without needing to embed numerous SVG documents in your page.

Demo

Ok, thanks for bearing with me, now that you know what is going on, take a look at the demo.

blog comments powered by Disqus
Monkey Small Crow Small