2012-01-16 11 views
5

Próbuję narysować 3 poniższe strzałki. Mogę prawidłowo narysować górny, ale nie mogę poprawnie dobrać pozostałych 2 strzałek. Używam Canvas HTML5 do rysowania tych strzał.Rysowanie krzywych strzałek w płótnie HTML5

enter image description here

Problem występuje z moich rozmów arktyczno. Po prostu nie mogę uzyskać prawidłowej krzywej z jakiegoś powodu. Może powinienem używać krzywej Beziera? Czy ktoś mógłby mi powiedzieć, jakie funkcje HTML5/JavaScript używam do tworzenia powyższych strzałek?

Czy możesz podać przykład jak uzyskać powyższe strzałki?

Herezje JSFiddle aby zobaczyć, co się dzieje źle: 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

można podać przykład (image) oczekiwanych wyników – rkmax

+0

@rkmax i napisali JSFiddle teraz pokazuje, że moja próba , strzałka jest zbyt przysadzista –

Odpowiedz

9

Więc mamy tę ścieżkę, która sprawia strzałę. Mam go adnotacją:

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

Chcemy utrzymać go jak najbardziej podobne z wyjątkiem chcemy dotrzeć do punktu końcowego (iz powrotem) w inny sposób niż tylko prostej. My absolutnie nie chcemy używać żadnych poleceń moveTo, z wyjątkiem pierwszego. To naprawdę utrudnia rzeczy i sprawia, że ​​trudno je zrozumieć. Unikałbym także używania arcTo, chyba że naprawdę potrzebujesz części łuku (jak w przypadku ciasta), ponieważ jest to dość mylące w porównaniu do innych poleceń ścieżki.

Użyjemy więc kwadratowych krzywych, które są jak bomby, ale mają tylko jeden punkt kontrolny, co czyni je całkiem prostymi. Działają, określając punkt kontrolny, taki jak this (on the left).

Stosujemy zatem ten sam dokładny kod strzały i wstawiamy dwa kwadratowe bahty, aby uzyskać chudą strzałę. Chcemy punkty kontrolne być jakoś „wewnątrz” masa strzałki, aby zginać quadratics do wewnątrz:

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

lub gruby, stawiamy punkt kontrolny na tej samej wysokości jak najwyższego i najniższego punktu oraz w tym samym X jako punktu końcowego:

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

żywo przykład tutaj: http://jsfiddle.net/Yp7DM/

Powiązane problemy