2012-01-16 11 views
5

Sto tentando di disegnare le 3 frecce di seguito. Posso disegnare correttamente quello superiore ma non riesco a disegnare correttamente le altre 2 teste di freccia. Sto usando HTML5 Canvas per disegnare queste frecce.Disegno di curve di direzione della freccia in tela HTML5

enter image description here

il problema si verifica con le mie chiamate arcTo. Non riesco proprio a ottenere la curva corretta per qualche motivo. Forse dovrei usare una curva di Bezier? Qualcuno potrebbe dirmi quali sono le funzioni HTML5/Javascript che uso per produrre i suddetti capi freccia?

Potete fornire un esempio di come ottenere le teste di freccia sopra?

Heres il JSFiddle per mostrare che cosa va male: http://jsfiddle.net/hJX8X/

<canvas id="testCanvas" width="400px" height="400px"> 

</canvas> 
<script type="text/javascript"> 
<!-- 
    var canvas = document.getElementById("testCanvas"); 
    var dc  = canvas.getContext("2d"); 

    // Points which are correct (when I draw straight lines its a perfect arrow 
    var width = 400; 
    var height = 100; 
    var arrowW = 0.35 * width; 
    var arrowH = 0.75 * height; 
    var p1  = {x: 0,    y: (height-arrowH)/2}; 
    var p2  = {x: (width-arrowW), y: (height-arrowH)/2}; 
    var p3  = {x: (width-arrowW), y: 0}; 
    var p4  = {x: width,   y: height/2}; 
    var p5  = {x: (width-arrowW), y: height}; 
    var p6  = {x: (width-arrowW), y: height-((height-arrowH)/2)}; 
    var p7  = {x: 0,    y: height-((height-arrowH)/2)}; 

    dc.clearRect(0, 0, canvas.width, canvas.height); 
    dc.fillStyle = "#FF0000"; 

    dc.beginPath(); 

    dc.moveTo(p1.x, p1.y); 
    dc.lineTo(p2.x, p2.y); 
    dc.lineTo(p3.x, p3.y);  
    dc.moveTo(p3.x, p3.y); 
    dc.arcTo(p3.x, p3.y, p4.x, p4.y, 50); 
    dc.moveTo(p4.x, p4.y); 
    dc.arcTo(p4.x, p4.y, p5.x, p5.y, 50); 
    dc.moveTo(p5.x, p5.y); 
    dc.lineTo(p6.x, p6.y); 
    dc.lineTo(p7.x, p7.y); 

    dc.closePath(); 
    dc.fill(); 

    /* Draw arrow without curves 
    dc.moveTo(p1.x, p1.y); 
    dc.lineTo(p2.x, p2.y); 
    dc.lineTo(p3.x, p3.y);  
    dc.lineTo(p4.x, p4.y); 
    dc.lineTo(p5.x, p5.y); 
    dc.lineTo(p6.x, p6.y); 
    dc.lineTo(p7.x, p7.y); 
    */ 
--> 
</script> 
+0

si può fornire un esempio (immagine) dei risultati attesi – rkmax

+0

@rkmax mi hanno inviato un JSFiddle ora che dimostra il mio tentativo , la testa della freccia è troppo tozza –

risposta

9

Quindi abbiamo questa strada che fa una freccia. Ho annotato che:

dc.moveTo(p1.x, p1.y); 
dc.lineTo(p2.x, p2.y); // end of main block 
dc.lineTo(p3.x, p3.y); // topmost point  
dc.lineTo(p4.x, p4.y); // endpoint 
dc.lineTo(p5.x, p5.y); // bottommost point 
dc.lineTo(p6.x, p6.y); // end at bottom point 
dc.lineTo(p7.x, p7.y); 

davvero vogliamo tenerlo il più possibile simili, tranne che vogliamo arrivare al punto finale (e ritorno) in un modo diverso di una semplice linea retta. Noi assolutamente non vogliamo usare alcun comando moveTo eccetto il primo. Questo davvero confonde le cose e le rende difficili da capire. Eviterei anche di usare arcTo a meno che tu non abbia davvero bisogno di parte di un arco (come in una torta) perché è piuttosto confuso rispetto agli altri comandi di percorso.

Quindi useremo curve quadratiche che sono come beziers ma hanno solo un punto di controllo, che le rende piuttosto semplici. Funzionano specificando un punto di controllo come this (on the left).

Quindi prendiamo lo stesso esatto codice di freccia e inseriamo due quadratici di bezier per fare una freccia sottile. Vogliamo che i punti di controllo per essere sorta "dentro" la massa della freccia per rendere il quadratiche curva verso l'interno:

dc.moveTo(p1.x, p1.y); 
dc.lineTo(p2.x, p2.y); // end of main block 
dc.lineTo(p3.x, p3.y); // topmost point 
// control point is based on p3 (topmost point) 
dc.quadraticCurveTo(p3.x + 20, p3.y + 30, p4.x, p4.y); // endpoint 
// control point is based on p5 (bottommost point) 
dc.quadraticCurveTo(p5.x + 20, p5.y - 30, p5.x, p5.y); // bottommost point 
dc.lineTo(p6.x, p6.y); // end at bottom point 
dc.lineTo(p7.x, p7.y); 

O un grasso uno, abbiamo messo il punto di controllo alla stessa altezza come il punto più in alto e in basso , e circa lo stesso X come endpoint:

dc.beginPath(); 
// Draw arrow without curves 
dc.moveTo(p1.x, p1.y); 
dc.lineTo(p2.x, p2.y); // end of main block 
dc.lineTo(p3.x, p3.y); // topmost point 
// control point is based on p3 (topmost point) 
dc.quadraticCurveTo(p3.x + 120, p3.y, p4.x, p4.y); // endpoint 
// control point is based on p5 (bottommost point) 
dc.quadraticCurveTo(p5.x + 120, p5.y, p5.x, p5.y); // bottommost point 
dc.lineTo(p6.x, p6.y); // end at bottom point 
dc.lineTo(p7.x, p7.y); 

vivo esempio qui: http://jsfiddle.net/Yp7DM/