lørdag 19. mars 2016

Double pointed arrows in HTML5 canvas


Drawing things like arrows might be hard in canvas, because there is no predefined function we can use. However with some trigonometry, this is not at all an exhausting task, but a bit complicated, especially when we are going to make the arrow double ended.


The arrow system is based upon this principle (and a bit trying and failing):




Based on that, I made the following JavaScript/HTML5 code:



<canvas id="arrows" height="500px" width="1000px"></canvas>

<script>

var canvas=document.getElementById("arrows");

var ctx=canvas.getContext("2d");

function draw_arrows(startX, startY, endX, endY, angle, width, length, color, ctx){

//The angle between the arrow and the canvas' x-axis. 
//Multiplied by 180/π for converting from radians to degrees.

 var main_angle=Math.atan2(startY-endY,startX-endX)*(180/Math.PI);

//Offsetting the given angle into the angle in the coordinate system of the canvas. 
//Multiplied with π/180 for converting back to radians, because that's what JavaScript uses.
 
 var offsetted_angle1=(main_angle+angle)*(Math.PI/180);
 
//We need to different angles, because the points of the arrows have different angles
//compared to the coordinate system.
 
 var offsetted_angle2=(main_angle-angle)*(Math.PI/180);
 
//Find the length of arrow on x-axis by using cosine.
 
 var xlength1=length*Math.cos(offsetted_angle1);
 
 var ylength1=length*Math.sin(offsetted_angle1);
 
 var xlength2=length*Math.cos(offsetted_angle2);
 
 var ylength2=length*Math.sin(offsetted_angle2);
 
 ctx.beginPath();
 
 var arrowX=startX-xlength1;
 
 var arrowY=startY-ylength1;

 ctx.moveTo(arrowX,arrowY);
 
 ctx.lineTo(startX,startY);
 
 arrowX=startX-xlength2;
 
 arrowY=startY-ylength2;
 
 ctx.lineTo(arrowX,arrowY);
 
 ctx.moveTo(startX,startY);
 
 ctx.lineTo(endX,endY);
 
//Reverse length on the other side
 
 arrowX=endX+xlength1;
 
 arrowY=endY+ylength1;
 
 ctx.moveTo(arrowX,arrowY);
 
 ctx.lineTo(endX,endY);
  
 arrowX=endX+xlength2;
 
 arrowY=endY+ylength2;
 
 ctx.lineTo(arrowX,arrowY);
 
 ctx.strokeStyle=color;
    
 ctx.lineWidth = width;
 
 ctx.stroke();
}

</script>



You can see a demonstration of the code below:



If there are any questions or suggestions of things I could have done better, please use comment section below.

Ingen kommentarer:

Legg inn en kommentar