web-dev-qa-db-fra.com

Dessiner une flèche sur une balise de toile

Je veux dessiner une flèche en utilisant la balise canvas, javascript. Je l'ai fait en utilisant la fonction quadratique, mais j'ai du mal à calculer l'angle de rotation de la flèche ...

Quelqu'un a un indice à ce sujet?

Je vous remercie

Aussi simple que je peux l'obtenir. Vous devrez préparer context.beginPath () et ajouter context.stroke () vous-même:

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));
}

Voici un exemple: http://stuff.titus-c.ch/arrow.html

76
Titus Cieslewski

Ok, la première réponse sur cette page m'a donc beaucoup aidé lorsque j'ai essayé de résoudre ce problème moi-même, bien que, comme quelqu'un l'a déjà dit, si vous avez une largeur de trait supérieure à 1 pixel, vous obtenez des formes amusantes. Le correctif suggéré par quelqu'un d'autre a presque fonctionné, mais j'ai quand même eu quelques problèmes lorsque j'essayais de choisir une flèche plus épaisse. Après plusieurs heures de jeu, j’ai pu combiner la solution ci-dessus avec quelques-uns de mes propres bricoleurs pour créer le code suivant qui tracera une flèche dans l’épaisseur souhaitée, sans déformer la forme de la flèche.

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();
            }

C'est maintenant le code que j'utilise dans mon programme. Pour éliminer le problème de la distorsion, j’ai trouvé que la solution était de poursuivre le trait de la pointe de la flèche à un point latéral, de l’autre côté, de la pointe vers le haut et de revenir au premier point latéral, puis de faire une remplir. Cela corrige la forme de la flèche.

J'espère que cela t'aides!

24
SteampunkWizard

Tu peux faire:

ctx.save();
ctx.translate(xOrigin, yOrigin);
ctx.rotate(angle);
 // draw your arrow, with its Origin at [0, 0]
ctx.restore();
7
Fabien Ménager

Voici une autre méthode pour dessiner des flèches. Il utilise la méthode du triangle à partir d’ici: https://stackoverflow.com/a/8937325/1828637

Une petite fonction d'assistance.

function canvas_arrow(context, fromx, fromy, tox, toy, r){
    var x_center = tox;
    var y_center = toy;

    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();
}

Et en voici une démonstration pour tracer des flèches au début et à la fin d'une ligne.

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){
	var x_center = tox;
	var y_center = toy;
	
	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();
}
<canvas id="c" width=300 height=300></canvas>

4
Noitidart

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

ctx.clearRect(0, 0, canvas.width, canvas.height);	
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();	
  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>

2
Aikon Mogwai

Ce code est similaire à la solution de Titus Cieslewski, peut-être que la flèche est un peu plus jolie:

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))));
}

cela fonctionne bien avec lineWidth > 1. Cela peut être utile pour tracer les axes x et y

2
user3719454

Étant donné la taille et la position de départ, le code suivant dessine la flèche pour vous.

<!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> 
2
nizam.sp
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);
  }
}
1
Ariel Mendoza

Voici la solution de travail

function draw_arrow(ctx,fx,fy,tx,ty){ //ctx is the context
    var angle=Math.atan2(ty-fy,tx-fx);
    ctx.moveTo(fx,fy); ctx.lineTo(tx,ty);
    var w=3.5; //width of arrow to one side. 7 pixels wide arrow is pretty
    ctx.strokeStyle="#4d4d4d"; ctx.fillStyle="#4d4d4d";
    angle=angle+Math.PI/2; tx=tx+w*Math.cos(angle); ty=ty+w*Math.sin(angle);
    ctx.lineTo(tx,ty);
  //Drawing an isosceles triangle of sides proportional to 2:7:2
    angle=angle-1.849096; tx=tx+w*3.5*Math.cos(angle); ty=ty+w*3.5*Math.sin(angle);
    ctx.lineTo(tx,ty);
    angle=angle-2.584993; tx=tx+w*3.5*Math.cos(angle); ty=ty+w*3.5*Math.sin(angle);
    ctx.lineTo(tx,ty);
    angle=angle-1.849096; tx=tx+w*Math.cos(angle); ty=ty+w*Math.sin(angle);
    ctx.lineTo(tx,ty);
    ctx.stroke(); ctx.fill();
}
0
ajk

Vous pouvez appuyer sur votre matrice, la faire pivoter, tracer votre flèche puis faire apparaître la matrice.

0
Clint

Cela fait quelque temps que je me bats avec ça ..__J'ai besoin de le faire en javascript et en c #. Pour javascript, j'ai trouvé une belle bibliothèque jCanvas .

Mon problème principal était de bien dessiner les flèches, ce que jCanvas fait parfaitement ..__Pour mon projet c #, j’ai procédé à la reverse engineering du code jCanvas.

Espérons que cela aide quelqu'un

0
hoeselvang