6. Dynamisches Verhalten im Browser mit Server
6.4 Zeichnen mit Canvas
Gehen Sie auf index-01-draw-by-hand.html. Ändern Sie die Größe Ihres Fensters und sehen Sie, wie sich der Canvas (die schwarze Box) anpasst, und wie seine Maße angegeben werden.
context.beginPath(); context.moveTo(0, 0); context.lineTo(300, 400); context.stroke(); context.lineTo(500, 400); context.stroke(); context.lineTo(500, 700); context.stroke(); context.lineTo(0, 0); context.stroke();Spielen Sie damit rum und zeichnen Sie ein paar Pfade. Dann tippen Sie
context.strokeStyle = 'brown'; context.stroke(); context.fillStyle = 'aquamarine'; context.stroke(); context.fill();Kreise und Kreisbögen können Sie zeichnen mit
context.beginPath(); context.strokeStyle = "red"; context.arc(0.5 * cw, 0.5 * ch, 10, 0, 2 * Math.PI); context.stroke(); context.fill();
Zeichnen Sie ein paar Sachen per Hand, um ein Gefühl dafür zu bekommen.
Ein Problem ist, dass die Graphik verschwindet, wenn die
die Fenstergröße verändern. Das Problem können wir lösen,
indem wir den Graphik erzeugenden Code in eine Funktion
drawCanvas
auslagern und die dann immer
aufrufen, wenn sich die Fenstergröße ändern:
window.onresize = drawCanvas;
{type : "circle", x : 200, y : 300, radius : 20,
fillColor = 'yellow', strokeColor = 'black'}
und entsprechendes für Liniensegmente (wenn Sie wollen,
natürlich gerne auch für ganze Pfade), und
schreiben eine Funktion drawElement(element)
,
die das dann zeichnet. Legen Sie in eine globalen Liste
von solchen Objekten an. Ihre Funktion drawCanvas()
soll dann die Liste durchgehen und alles zeichnen.
Relative Koordinaten
Eine weitere unschöne Eigenschaft ist, dass
die Funktionen lineTo()
etc.
absolute Koordinaten verwenden, also in Pixeln, mit (0,0)
als linke obere Ecke das Canvas-Objekts.
drawCanvas()
, so dass sie relative
Koordinaten verwendet, zum Beispiel mit (0,0)
links oben oder (1,1)
rechts unten.
Hinweis. Je nach Anwendung kann es mehr
Sinn machen, dass (0,0)
links unten steht
und höhere y-Koordinaten dann weiter oben stehen.
Mausposition lesen
- Jeder Mausklick soll einen Kreis an dem angegebenen Ort hinzufügen, so dass Sie mit Mausklicks "zeichnen" können.
- Wenn Sie ambitioniert sind: lassen Sie den Benutzer über Knöpfe oder Radio-Buttons zwischen zwei Zeichenmodi wechseln: Kreise zeichnen oder Liniensegmente zeichnen.
{"type" : "circle", "x" : "0.2", "y" : "0.4"}
und so weiter.
Wenn der Server eine Nachricht bekommt, soll er die einfach an alle Benutzer weiterleiten.
Wenn ein Benutzer (also die HTML-Seite) eine Websocket-Nachricht erhält,
soll sie diese mit JSON.parse
wieder dekodieren. Wenn
es ein bekanntes Graphik-Objekt ist, also zum Beispiel
element.type == "circle"
oder
element.type == "line"
, dann soll das Objekt der Liste
von Graphik-Objekten hinzugefügt (und dann auch angezeigt) werden.
Erweitern Sie die Seite, dass mehrere Personen miteinander / gegeneinander spielen können. Der Server könnte zum Beispiel regelmäßig die neuen Positionen berechnen und an alle schicken. Die Spieler schicken ihre Richtungsänderungen an den Server, der das dann mit in Betracht zieht.
Hinweis. Seien Sie fürs erste nicht zu ehrgeizig. Sagen wir einfach, alle Clients, die sich verbinden, werden auf ein großes, gemeinsames Spielbrett geworfen.
- Wenn man sich anmeldet (mit Namen!), sieht man eine Liste aller Spieler, die noch offen für weitere Spieler sind.
- Man kann create new game klicken.
- Die Personn, die das Spiel erschaffen hat, kann es starten, wenn sie meint, dass genügend Personen drin sind.
- Der Server weist einem Spieler die Rolle des Gejagten zu; dieser ist etwas schneller als der Rest; die anderen müssen ihn fangen.
Tips
Nehmen Sie an, innerhalb einer Zeichenroutine (z.B.drawCanvas()
rufen Sie eine Unterfunktion drawText(text)
oder wie auch immer auf, die text
einfügt, und zwar immer schwarz. Dann wird
irgendwo in drawText(text)
die Code-Zeile
context.strokeStyle = 'black';
stehen. Wenn drawText()
zurückkehrt und
die umgebende Funktion drawCanvas()
weitergeht, steht nun
context.strokeStyle
immer noch auf 'black'
, was zu Fehlern führen
könnte.
Ein Hack wäre
let old_color = context.strokeStyle; drawText(text); context.strokeStyle = old_color;Aber vielleicht gibt es noch mehr Parameter, die Sie sich "merken" wollen. Besser, Sie verwenden
context.save()
und context.restore()
:
context.save(); drawText(text); context.restore();Damit werden die Kontext-Parameter, die vor dem Aufruf von
drawText(text)
galten,
wiederhergestellt.