2009-04-30 14 views
34

Quiero dibujar una flecha con la etiqueta canvas, javascript. Lo hice usando la función cuadrática, pero estoy teniendo problemas para calcular el ángulo de rotación de la flecha ...Dibujar flecha en la etiqueta de lona

¿Alguien tiene una pista sobre esto?

Gracias

Respuesta

1

puede llevar a su matriz, girarlo, llamar su flecha y luego estallar la matriz.

7

que puede hacer:

ctx.save(); 
ctx.translate(xOrigin, yOrigin); 
ctx.rotate(angle); 
// draw your arrow, with its origin at [0, 0] 
ctx.restore(); 
1
function RTEShape() 
{ 
    this.x = 50; 
    this.y = 50; 
    this.w = 100; // default width and height? 
    this.h = 100; 
    this.fill = '#444444'; 
    this.text = "Test String"; 
    this.type; 
    this.color; 
    this.size = 6;  

    // The selection color and width. Right now we have a red selection with a small width 
    this.mySelColor = '#CC0000'; 
    this.mySelWidth = 2; 
    this.mySelBoxColor = 'darkred';// New for selection boxes 
    this.mySelBoxSize = 6; 
} 

RTEShape.prototype.buildArrow = function(canvas) 
{ 
    this.type = "arrow"; 

    // Make sure we don't execute when canvas isn't supported 
    if (canvas.getContext){ 

    // use getContext to use the canvas for drawing 
    var ctx = canvas.getContext('2d');   

    var oneThirdX = this.x + (this.w/3);    
    var twoThirdX = this.x + ((this.w*2)/3); 

    var oneFifthY = this.y - (this.y/5);  
    var twoFifthY = this.y - ((this.y*3)/5); 

    /**/ 
    //ctx.beginPath(); 
    ctx.moveTo(oneThirdX,this.y); // 125,125 
    ctx.lineTo(oneThirdX,oneFifthY); // 125,105 

    ctx.lineTo(this.x*2,oneFifthY); // 225,105  
    ctx.lineTo(this.x*2,twoFifthY); // 225,65 

    ctx.lineTo(oneThirdX,twoFifthY); // 125,65  
    ctx.lineTo(oneThirdX,(this.y/5)); // 125,45 

    ctx.lineTo(this.x,(this.y+(this.y/5))/2); // 45,85 

     ctx.fillStyle = "green"; 
    ctx.fill(); 

    ctx.fillStyle = "yellow"; 
    ctx.fillRect(this.x,this.y,this.w,this.h); 

    } else { 
    alert('Error on buildArrow!\n'+err.description); 
    } 
} 
63

Tan simple como lo puedo conseguir. Vas a tener que anteponer context.beginPath() y anexar context.stroke() a ti mismo:

function canvas_arrow(context, fromx, fromy, tox, toy){ 
    var headlen = 10; // length of head in pixels 
    var angle = Math.atan2(toy-fromy,tox-fromx); 
    context.moveTo(fromx, fromy); 
    context.lineTo(tox, toy); 
    context.lineTo(tox-headlen*Math.cos(angle-Math.PI/6),toy-headlen*Math.sin(angle-Math.PI/6)); 
    context.moveTo(tox, toy); 
    context.lineTo(tox-headlen*Math.cos(angle+Math.PI/6),toy-headlen*Math.sin(angle+Math.PI/6)); 
} 

He aquí una muestra: http://stuff.titus-c.ch/arrow.html

+1

que produce una forma extraña, desea deshacerse de ese último movimiento y añadir al final lineTo (tox, juguete) – owook

+1

la función no funciona bien cuando lineWidth no es == 1 –

+0

funciona bien con 2: P '+ 1' –

2

dado un tamaño y la posición de partida, después de dibujar el código se flecha para ti

<!DOCTYPE HTML> 
<html> 
    <head> 
     <style> 
      body { 
       margin: 0px; 
       padding: 0px; 
      } 

      #myCanvas { 
       border: 1px solid #9C9898; 
      } 
     </style> 
     <script> 
      function draw_arrow(context, startX, startY, size) 
      { 
       var arrowX = startX + 0.75*size; 
       var arrowTopY = startY - 0.707*(0.25*size); 
       var arrowBottomY = startY + 0.707*(0.25*size); 
       context.moveTo(startX, startY); 
       context.lineTo(startX+size, startX); 
       context.lineTo(arrowX, arrowTopY); 
       context.moveTo(startX+size, startX); 
       context.lineTo(arrowX, arrowBottomY); 
       context.stroke(); 
      } 
      window.onload = function(){ 
       var canvas = document.getElementById("myCanvas"); 
       var context = canvas.getContext("2d"); 
       var startX = 50; 
       var startY = 50; 
       var size = 100; 
       context.lineWidth = 2; 
       draw_arrow(context, startX, startY, size); 
      }; 
     </script> 
    </head> 
    <body onmousedown="return false;"> 
     <canvas id="myCanvas" width="578" height="200"> 
     </canvas> 

    </body> 
</html> 
16

Ok, por lo que la primera respuesta en esta página me ha ayudado en gran medida cuando yo estaba tratando de entender este problema a mí mismo, a pesar de que otra persona ya se ha dicho, si tiene un ancho de línea mayor que 1 píxel se obtiene formas divertidas . La solución que alguien más sugirió casi funcionó, pero todavía tenía algunos problemas cuando intentaba obtener una flecha de ancho más grueso. Después de varias horas de jugar con él, pude combinar la solución anterior con algunos de mis propios retoques para obtener el siguiente código que dibujará una flecha al grosor que desee sin distorsionar la forma de la flecha.

function drawArrow(fromx, fromy, tox, toy){ 
       //variables to be used when creating the arrow 
       var c = document.getElementById("myCanvas"); 
       var ctx = c.getContext("2d"); 
       var headlen = 10; 

       var angle = Math.atan2(toy-fromy,tox-fromx); 

       //starting path of the arrow from the start square to the end square and drawing the stroke 
       ctx.beginPath(); 
       ctx.moveTo(fromx, fromy); 
       ctx.lineTo(tox, toy); 
       ctx.strokeStyle = "#cc0000"; 
       ctx.lineWidth = 22; 
       ctx.stroke(); 

       //starting a new path from the head of the arrow to one of the sides of the point 
       ctx.beginPath(); 
       ctx.moveTo(tox, toy); 
       ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7)); 

       //path from the side point of the arrow, to the other side point 
       ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7)); 

       //path from the side point back to the tip of the arrow, and then again to the opposite side point 
       ctx.lineTo(tox, toy); 
       ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7)); 

       //draws the paths created above 
       ctx.strokeStyle = "#cc0000"; 
       ctx.lineWidth = 22; 
       ctx.stroke(); 
       ctx.fillStyle = "#cc0000"; 
       ctx.fill(); 
      } 

Este es ahora el código que estoy usando en mi programa. Lo que descubrí que era la clave para eliminar el problema de la distorsión fue continuar el trazo desde la punta de la flecha a un punto lateral, al otro punto lateral, de vuelta a la punta, y de vuelta al primer punto lateral, y luego hacer un llenar. Esto corrigió la forma de la flecha.

Espero que esto ayude!

+0

gracias, esto funciona genial! – satnam

+0

¡Lo has clavado, hombre! – Exception

1

Aquí hay otro método para dibujar flechas. Utiliza el método de triángulo desde aquí: https://stackoverflow.com/a/8937325/1828637

Una pequeña función de ayuda.

función canvas_arrow (context, fromx, fromy, tox, toy, r) { var x_center = tox; var y_center = juguete;

var angle; 
var x; 
var y; 

context.beginPath(); 

angle = Math.atan2(toy-fromy,tox-fromx) 
x = r*Math.cos(angle) + x_center; 
y = r*Math.sin(angle) + y_center; 

context.moveTo(x, y); 

angle += (1/3)*(2*Math.PI) 
x = r*Math.cos(angle) + x_center; 
y = r*Math.sin(angle) + y_center; 

context.lineTo(x, y); 

angle += (1/3)*(2*Math.PI) 
x = r*Math.cos(angle) + x_center; 
y = r*Math.sin(angle) + y_center; 

context.lineTo(x, y); 

context.closePath(); 

context.fill(); 

}

Y aquí es una demostración de que para dibujar flechas al principio y al final de una línea.

var can = document.getElementById('c'); 
 
var ctx = can.getContext('2d'); 
 

 
ctx.lineWidth = 10; 
 
ctx.strokeStyle = 'steelblue'; 
 
ctx.fillStyle = 'steelbllue'; // for the triangle fill 
 
ctx.lineJoin = 'butt'; 
 

 
ctx.beginPath(); 
 
ctx.moveTo(50, 50); 
 
ctx.lineTo(150, 150); 
 
ctx.stroke(); 
 

 
canvas_arrow(ctx, 50, 50, 150, 150, 10); 
 
canvas_arrow(ctx, 150, 150, 50, 50, 10); 
 

 
function canvas_arrow(context, fromx, fromy, tox, toy, r){ 
 
\t var x_center = tox; 
 
\t var y_center = toy; 
 
\t 
 
\t var angle; 
 
\t var x; 
 
\t var y; 
 
\t 
 
\t context.beginPath(); 
 
\t 
 
\t angle = Math.atan2(toy-fromy,tox-fromx) 
 
\t x = r*Math.cos(angle) + x_center; 
 
\t y = r*Math.sin(angle) + y_center; 
 

 
\t context.moveTo(x, y); 
 
\t 
 
\t angle += (1/3)*(2*Math.PI) 
 
\t x = r*Math.cos(angle) + x_center; 
 
\t y = r*Math.sin(angle) + y_center; 
 
\t 
 
\t context.lineTo(x, y); 
 
\t 
 
\t angle += (1/3)*(2*Math.PI) 
 
\t x = r*Math.cos(angle) + x_center; 
 
\t y = r*Math.sin(angle) + y_center; 
 
\t 
 
\t context.lineTo(x, y); 
 
\t 
 
\t context.closePath(); 
 
\t 
 
\t context.fill(); 
 
}
<canvas id="c" width=300 height=300></canvas>

1

Este código es similar a la solución de Tito Cieslewski, tal vez la flecha es un poco más agradable:

function canvasDrawArrow(context, fromx, fromy, tox, toy) { 
    var headlen = 10.0; 
    var back = 4.0; 
    var angle1 = Math.PI/13.0; 
    var angle2 = Math.atan2(toy - fromy, tox - fromx); 
    var diff1 = angle2 - angle1; 
    var diff2 = angle2 + angle1; 
    var xx = getBack(back, fromx, fromy, tox, toy); 
    var yy = getBack(back, fromy, fromx, toy, tox); 

    context.moveTo(fromx, fromy); 
    context.lineTo(tox, toy); 

    context.moveTo(xx, yy); 
    context.lineTo(xx - headlen * Math.cos(diff1), yy - headlen * Math.sin(diff1)); 

    context.moveTo(xx, yy); 
    context.lineTo(xx - headlen * Math.cos(diff2), yy - headlen * Math.sin(diff2)); 
} 

function getBack(len, x1, y1, x2, y2) { 
    return x2 - (len * (x2 - x1)/(Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2)))); 
} 

esto funciona bien con lineWidth > 1. Puede ser útil cuando dibujo x y y eje

0

var canvas = document.getElementById('canvas'); 
 
var ctx = canvas.getContext('2d'); 
 

 
ctx.clearRect(0, 0, canvas.width, canvas.height); \t 
 
arrow({x: 10, y: 10}, {x: 100, y: 170}, 10); 
 
arrow({x: 40, y: 250}, {x: 10, y: 70}, 5); 
 

 

 
function arrow (p1, p2, size) { 
 
    var angle = Math.atan2((p2.y - p1.y) , (p2.x - p1.x)); 
 
    var hyp = Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); 
 

 
    ctx.save(); 
 
    ctx.translate(p1.x, p1.y); 
 
    ctx.rotate(angle); 
 

 
    // line 
 
    ctx.beginPath(); \t 
 
    ctx.moveTo(0, 0); 
 
    ctx.lineTo(hyp - size, 0); 
 
    ctx.stroke(); 
 

 
    // triangle 
 
    ctx.fillStyle = 'blue'; 
 
    ctx.beginPath(); 
 
    ctx.lineTo(hyp - size, size); 
 
    ctx.lineTo(hyp, 0); 
 
    ctx.lineTo(hyp - size, -size); 
 
    ctx.fill(); 
 

 
    ctx.restore(); 
 
}
<canvas id = "canvas" width = "300" height = "400"></canvas>

Cuestiones relacionadas