2010-07-02 24 views
46

Teil einer Webanwendung, die ich entwickle, erfordert, dass ich Balkendiagramme zur Anzeige verschiedener Informationen erstelle. Ich dachte, wenn der Browser des Benutzers in der Lage ist, würde ich sie mit dem HTML5-Canvas-Element zeichnen. Ich habe keine Probleme, Linien und Balken für meine Graphen zu zeichnen, aber wenn es darum geht, die Achsen, die Balken oder die Linien zu beschriften, rannte ich in einen Haken. Wie zeichne ich gedrehten Text auf ein Canvas-Element, damit es mit dem Element, das es kennzeichnet, übereinstimmt? Ein paar Beispiele sind:Gezeichneten Text auf einer HTML5-Leinwand zeichnen

  • Rotate Text um 90 Grad gegen Uhrzeigersinn, um die Y-Achse
  • Rotate Text um 90 Grad gegen Uhrzeigersinn zu etikettieren Stäbe
  • Drehen von Text auf einer vertikalen Balkendiagramm zur Kennzeichnung einer willkürlichen betragen Label Linien auf einem Liniendiagramm

würden Alle Zeiger geschätzt.

+0

Haben Sie grübelten die Suche in vorhandenen Grafiklösungen anstatt zu versuchen, Ihre eigenen zu bauen ? flot (http://code.google.com/p/flot/) ist ein Beispiel, das Canvas verwendet. – Bartek

Antwort

29

Wie andere bereits erwähnt haben, möchten Sie wahrscheinlich eine bestehende Grafiklösung wiederverwenden, aber rotierender Text ist nicht allzu schwierig. Die etwas verwirrend Bit (für mich) ist, dass Sie den gesamten Kontext und dann ziehen auf ihn drehen:

ctx.rotate(Math.PI*2/(i*6)); 

Die angle is in radians. Der Code ist taken from this example, was meiner Meinung nach für die transformations part of the MDC canvas tutorial gemacht wurde.

Eine vollständige Lösung finden Sie unter the answer below.

98

Dies zu schreiben, um anderen mit ähnlichen Problemen zu helfen. Ich löste dieses Problem mit einem fünfstufigen Ansatz - Speichern Sie den Kontext, übersetzen Sie den Kontext, drehen Sie den Kontext, zeichnen Sie den Text und stellen Sie den Kontext in den gespeicherten Zustand zurück.

Ich denke an Übersetzungen und transformiert in den Kontext als manipuliert das Koordinatenraster überlagert auf der Leinwand. Standardmäßig beginnt der Ursprung (0,0) in der oberen linken Ecke der Leinwand. X nimmt von links nach rechts zu, Y von oben nach unten. Wenn Sie ein "L" mit Ihrem Zeigefinger und Daumen auf Ihrer linken Hand machen und es mit Ihrem Daumen nach unten vor sich halten, würde Ihr Daumen in die Richtung des zunehmenden Y zeigen und Ihr Zeigefinger würde in die Richtung zeigen Ich weiß, dass es elementar ist, aber ich finde es hilfreich, wenn ich über Übersetzungen und Drehungen nachdenke. Hier ist der Grund:

Wenn Sie den Kontext übersetzen, verschieben Sie den Ursprung des Koordinatenrasters an eine neue Position auf der Zeichenfläche. Wenn Sie den Kontext drehen, denken Sie daran, das "L", das Sie mit Ihrer linken Hand gemacht haben, im Uhrzeigersinn um den Betrag zu drehen, der durch den Winkel angegeben wird, den Sie im Bogenmaß über den Ursprung angeben. Geben Sie bei StrokeText oder FillText Ihre Koordinaten in Bezug auf die neu ausgerichteten Achsen ein. Um Ihren Text so zu orientieren, dass er von unten nach oben lesbar ist, würden Sie ihn an eine Position unterhalb der Stelle verschieben, an der Sie die Beschriftungen beginnen möchten. Drehen Sie ihn um -90 Grad und füllen oder streichen Sie Text, wobei Sie jede Beschriftung entlang der gedrehten x-Achse versetzen.So etwas sollte funktionieren:

context.save(); 
context.translate(newx, newy); 
context.rotate(-Math.PI/2); 
context.textAlign = "center"; 
context.fillText("Your Label Here", labelXposition, 0); 
context.restore(); 

.restore() setzt den Kontext wieder in den Zustand sie hatten, als Sie .save() aufgerufen - praktisch für die Dinge wieder auf „normal“ zurückkehrt.


+2

große translate/rotate Erklärung. +1 –

+6

Wenn Sie den Winkel auf etwas bestimmtes einstellen möchten, können Sie tun: 'context.rotate (Winkel * (Math.PI/180));' – PaulBGD

+0

Mehr als der Code, ich liebe Ihre Erklärung. – Sorter

21

Während dies eine Art Follow-up zu der vorherigen Antwort ist, fügt es ein wenig (hoffentlich) hinzu.

Hauptsächlich möchte ich klarstellen, dass wir normalerweise Dinge wie draw a rectangle at 10, 3 zeichnen. Wenn wir also so darüber nachdenken: move origin to 10, 3, dann draw rectangle at 0, 0. Dann müssen wir nur noch eine Drehung dazwischen hinzufügen.

Ein weiterer wichtiger Punkt ist die Ausrichtung des Textes. Am einfachsten ist es, den Text auf 0, 0 zu zeichnen, sodass wir die richtige Ausrichtung verwenden können, ohne die Textbreite zu messen.

Wir sollten den Text immer noch um einen Betrag verschieben, um ihn vertikal zu zentrieren, und leider hat Canvas keine große Zeilenhöhenunterstützung, also ist das eine Vermutungs - und Kontrollsache (korrigiert mich, wenn es etwas Besseres gibt).

Ich habe 3 Beispiele erstellt, die einen Punkt und einen Text mit 3 Ausrichtungen bieten, um anzuzeigen, wo der tatsächliche Punkt auf dem Bildschirm ist, wo die Schrift gehen wird.

enter image description here

var font, lineHeight, x, y; 

x = 100; 
y = 100; 
font = 20; 
lineHeight = 15; // this is guess and check as far as I know 
this.context.font = font + 'px Arial'; 


// Right Aligned 
this.context.save(); 
this.context.translate(x, y); 
this.context.rotate(-Math.PI/4); 

this.context.textAlign = 'right'; 
this.context.fillText('right', 0, lineHeight/2); 

this.context.restore(); 

this.context.fillStyle = 'red'; 
this.context.fillRect(x, y, 2, 2); 


// Center 
this.context.fillStyle = 'black'; 
x = 150; 
y = 100; 

this.context.save(); 
this.context.translate(x, y); 
this.context.rotate(-Math.PI/4); 

this.context.textAlign = 'center'; 
this.context.fillText('center', 0, lineHeight/2); 

this.context.restore(); 

this.context.fillStyle = 'red'; 
this.context.fillRect(x, y, 2, 2); 


// Left 
this.context.fillStyle = 'black'; 
x = 200; 
y = 100; 

this.context.save(); 
this.context.translate(x, y); 
this.context.rotate(-Math.PI/4); 

this.context.textAlign = 'left'; 
this.context.fillText('left', 0, lineHeight/2); 

this.context.restore(); 

this.context.fillStyle = 'red'; 
this.context.fillRect(x, y, 2, 2); 

Die Linie this.context.fillText('right', 0, lineHeight/2); ist im Grunde 0, 0, außer dass wir etwas für den Text bewegen nahe dem Punkt zentriert werden

Verwandte Themen