Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

I am trying to add arrowheads to the ends of lines drawn by the user on HTML 5 Canvas. Of course, the big problem is figuring out which way the line is pointing. I have tried creating a stack keeping track of the points along the line then popping 5-20 points off the stack to get the direction of the end of the line. This method has two problems. If the stack is two short, no arrow is drawn (I might be able to handle this by first checking the size of the stack and adjust the number of pops). The bigger problem is if the user moves the mouse a little as he releases the button, the arrow may point the wrong way (see the image.) You can see this solution in action at www.barnwellmd.com/PainDiagram/PainDiagram.html (click on referred pain to see the lines with the arrowheads). Below is the code using the stack (just the pertinent code).

Any suggestions? TIA

Any suggestions? TIA

```
// This is called when you start holding down the mouse button.
// This starts the pencil drawing.
this.mousedown = function (ev) {
stackx = new Array();
stacky = new Array();
context.lineWidth = 10;
context.beginPath();
tool.started = true;
};
// This function is called every time you move the mouse.
this.mousemove = function (ev) {
if (tool.started) {
stackx.push(ev._x);
stacky.push(ev._y);
context.lineTo(ev._x, ev._y);
context.stroke();
}
// This is called when you release the mouse button.
this.mouseup = function (ev) {
if (tool.started)
{
for (var i = 0; i < 20; i++)
{
stackx.pop();
stacky.pop();
}
var angle = Math.atan2(ev._y-stacky.pop(),ev._x-stackx.pop());
context.beginPath();
context.moveTo(ev._x, ev._y);
context.lineTo(ev._x-20*Math.cos(angle-Math.PI/6),ev._y-20*Math.sin(angle-Math.PI/6));
context.lineTo(ev._x-20*Math.cos(angle+Math.PI/6),ev._y-20*Math.sin(angle+Math.PI/6));
context.closePath();
context . fillStyle = color_value;
context.fill();
}
tool.started = false;
tool.mousemove(ev);
}
```

Experts Exchange Solution brought to you by

Enjoy your complimentary solution view.

Get every solution instantly with premium.
Start your 7-day free trial.

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

```
this.mousemove = function (ev) {
if (tool.started) {
stackx.push(ev._x);
stacky.push(ev._y);
if(stackx.length % 20 == 0){ //draw a line every time the array length is divisible by 20
context.lineTo(ev._x, ev._y);
context.stroke();
}
}
};
```

```
var lastXseg, lastYseg, prevXseg, prevYseg;
this.mousemove = function (ev) {
if (tool.started) {
stackx.push(ev._x);
stacky.push(ev._y);
if (color_value == "#FF7F50") //referred pain
{
if(stackx.length % 20 == 0){
if(stackx.length == 20){
prevXseg = stackx[0];
prevYseg = stacky[0];
}else{
prevXseg = lastXseg;
prevYseg = lastYseg;
}
lastXseg = ev._x;
lastYseg = ev._y;
context.lineTo(ev._x, ev._y);
context.stroke();
}
}else{
context.lineTo(ev._x, ev._y);
context.stroke();
}
}
};
```

I am saving the beginning and end points of each 20 pixel long line segment and using them later in the mouseup event to get the segment's angle so I can apply the arrow head in the correct orientation. Because the segments are straight for every 20 pixels and any ending short segments are not recorded, the arrows are consistently pointing in the proper direction to the line.

B.T.W, I am using the canvasutilities.js file from this site to draw the arrow heads. Your method is clever, but because I flunked trigonometry, I don't understand it : )

http://www.dbp-consulting.

The arrowheads draw by the other routine are very nice. I think I'll switch to them.

Thanks again for your help. I have one more question I would appreciate your help with: http:Q_27647700.html.

```
this.mousedown = function (ev) {
segCount = 0;
if (color_value == "#FF7F50") //referred pain
{
context.lineWidth = 2;
reptSeg = 7;
}
else
{
context.lineWidth = 10;
reptSeg = 1;
}
}:
this.mousemove = function (ev)
{
if (tool.started)
{
if(!segCount)
{
prevX = lastX;
prevY = lastY;
lastX = ev._x;
lastY = ev._y;
segCount = reptSeg;
context.lineTo(ev._x, ev._y);
context.stroke();
}
segCount--;
}
};
this.mouseup = function (ev) {
if (tool.started)
{
if (color_value == "#FF7F50")
{
var angle = Math.atan2(lastY-prevY,lastX-prevX);
context.beginPath();
context.moveTo(lastX+15*Math.cos(angle),lastY+15*Math.sin(angle));
context.lineTo(lastX-7*Math.cos(angle-Math.PI/4),lastY-7*Math.sin(angle-Math.PI/4));
context.lineTo(lastX-7*Math.cos(angle+Math.PI/4),lastY-7*Math.sin(angle+Math.PI/4));
context.closePath();
context . fillStyle = color_value;
context.fill();
}
...
```

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
JavaScript

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Experts Exchange Solution brought to you by

Enjoy your complimentary solution view.

Get every solution instantly with premium.
Start your 7-day free trial.