0 Replies - 4290 Views - Last Post: 18 July 2014 - 03:17 AM

#1 Blindman67  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 133
  • View blog
  • Posts: 590
  • Joined: 15-March 14

Annotating a line. Canvas Snippet

Post icon  Posted 18 July 2014 - 03:17 AM

Annotating a line. Canvas Snippet

There are many situations that you are drawing lines on a canvas and you need to annotate that line. This snippet present the quickest way to do this in Javascript.

Given a line p1= {x:?,y:?} and p2 = {x:?,y:?} draw text along it.

For speed we will use all points as basic types, thus the line become x1,y1,x2,y2

First we need to get the angle the line is going, To get the direction of the line in the same space that the canvas uses. Rotating positive is rotating in a clockwise direction.
var getDiirectionOld = function(x1, y1, x2, y2) {
   var angV = Math.acos((x2 - x1) / Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2,2)));
   if (y1- y2 > 0) return- angV;
   return angV;
}


ECMAScript6 has the new math function hypot that calculates the hypotenuses. This makes the function slightly faster
var getDiirectionNew = function(x1, y1, x2, y2) {
   if (y1- y2 > 0) return  -Math.acos((x2 - x1) / Math.hypt(x1-x2,y1-y2));
   return  Math.acos((x2 - x1) / Math.hypt(x1-x2,y1-y2));
}


Use the old one if you want to be compatible with older script versions or do a test and assign the function at startup
var getDirection = getDirectionOld;
if(Math.hypot){
     getDirection = getDirectionNew;
}

I will put the function inline as we get some speed improvement doing so.

This function returns the angle in radians from 0 to Math.PI*2 of the line x1,y1,x2,y2;

We need to think in terms of the transformed coordinates now. When we move in the x direction we will move along the line from its start to its end. If we move along the y direction we move away from and towards the line. Everything relative to the start of the line (the origin).

To do this we need two vectors. Directions in terms of x and y to move in this new coordinate space.

Get the line direction.
var lineAng = getDirection(x1,y1,x2,y2);


Get the vector for moving along the line.
var xVecX = Math.sin(lineAng);
var xVecY = Math.cos(lineAng);


Get the vector for moving perpendicular to the line
var yVecX = -Math.cos(lineAng);
var yVecY = Math.sin(lineAng);


Now we have almost everything we need to draw the text. The only thing we have left is finding where along the line we want the text. We will need the length of the line.
var len =  Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2,2));


or if you are using ECMAScript6
var len =  Math.hypot(x1-x2,y1-y2);


To now set the canvas transform we simply plug the vectors and start pos into the setTransform function.

 // Clears transform and then sets it to the line
 // First two numbers are the vector along the line
 // second two numbers are the vector perpendicular to the line
 // the last two numbers are the new origin, the start of the line.
 ctx.setTransform(xVecX, xVecY, yVecX, yVecY, x1, y1);



The function we are creating will allow for aligning text horizontal and vertically. We will add a option to force the text always to read from left to right, and we want the text to fit the line, to stretch it along the line to fit, to expand it to fit, or to not fit the line.

The complete function. Read the comments to find out how it works.
Spoiler


Example HTML showing all the options for the function. Copy and past this into a HTML document. Tested and run on current versions of Chrome, IE11, and Firefox. July 2014.
Spoiler


The code minus the comments.
Spoiler


Hope you find this useful. :)/>/>

Is This A Good Question/Topic? 1
  • +

Page 1 of 1