Placer l'étiquette de texte le long d'une ligne sur un canevas

J'ai réussi à dessiner une ligne sur une toile en utilisant html5:

ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); 

Cela marche. Je souhaite maintenant "annoter" la ligne avec du texte. Donc, fondamentalement, je veux qu'il y ait un texte personnalisé (par exemple, tout ce que je passe) dans la longueur de la ligne. La difficulté est que la ligne peut apparaître dans n'importe quelle orientation (p. Ex. Avoir une pente) afin que le texte soit orienté en conséquence. Des idées sur comment commencer?

J'ai créé un exemple de ceci sur mon site . En général, vous souhaitez:

  1. translate le contexte au point d'ancrage du texte, puis
  2. rotate le contexte par le montant (en radians) que vous désirez, puis
  3. fillText le fillText comme d'habitude.

J'ai inclus la partie pertinente de mon exemple ci-dessous; Je laisse comme un exercice au lecteur de détecter quand le texte est à l'envers et de le gérer comme vous le souhaitez . Modifier : affiche la source sur mon site pour obtenir un code supplémentaire qui maintient le texte en position verticale et l'enracine automatiquement.

 function drawLabel( ctx, text, p1, p2, alignment, padding ){ if (!alignment) alignment = 'center'; if (!padding) padding = 0; var dx = p2.x - p1.x; var dy = p2.y - p1.y; var p, pad; if (alignment=='center'){ p = p1; pad = 1/2; } else { var left = alignment=='left'; p = left ? p1 : p2; pad = padding / Math.sqrt(dx*dx+dy*dy) * (left ? 1 : -1); } ctx.save(); ctx.textAlign = alignment; ctx.translate(p.x+dx*pad,p.y+dy*pad); ctx.rotate(Math.atan2(dy,dx)); ctx.fillText(text,0,0); ctx.restore(); } 

Pour Firefox, vous avez également la possibilité d'utiliser mozTextAlongPath .

Je l'ai utilisé et cela a fonctionné =) Je viens de changer quelque chose de sorte que lorsque je fais tourner le noeud, l'étiquette est toujours en bonne position pour être lue:

Dans ma fonction de redimensionnement, j'ai mis quelque chose comme ça:

 particleSystem.eachEdge(function(edge, pt1, pt2){ // edge: {source:Node, target:Node, length:#, data:{}} // pt1: {x:#, y:#} source position in screen coords // pt2: {x:#, y:#} target position in screen coords // draw a line from pt1 to pt2 var dx = (pt2.x - pt1.x); var dy = (pt2.y - pt1.y); var p, pad; var alignment = "center"; //ctx.label(edge.data.role,dx,dy,5,90,14); ctx.strokeStyle = "rgba(0,0,0, .333)"; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(pt1.x, pt1.y); ctx.lineTo(pt2.x, pt2.y); ctx.stroke(); p = pt1; pad = 1/2; ctx.save(); ctx.textAlign = alignment; ctx.translate(p.x+dx*pad,p.y+dy*pad); if(dx < 0) { ctx.rotate(Math.atan2(dy,dx) - Math.PI); //to avoid label upside down } else { ctx.rotate(Math.atan2(dy,dx)); } ctx.fillStyle = "black" ctx.fillText(edge.data.role,0,0); ctx.restore(); }) 

Merci,

Dámaris.