Antworten auf deine Fragen:
Neues Thema erstellen

Straßenmittelstriche Animiert für HTML5

IVIrcus

Noch nicht viel geschrieben

Moin allerseits,

ich stehe bei der Umsetzung eines HTML5 Projektes (canvas) auf dem Schlauch. Meine Absicht ist es u.a. eine kleine Straße zu simulieren, in dem sich dich Straßenmarkierungen (Mittelstreifen - gestrichelt) bewegen.

Auf folgende Art erreiche ich, dass sich eine einzelne Linie schräg abwärts bewegt. (Man schaut seitlich auf die Straße). Ziel ist es aber, dass über die gesamte Canvas-Height mehrere Striche verlaufen.
Nach Möglichkeit müssten die Striche oben (sprich i.d. Nähe des Horizonts) kleiner und enger beieinander liegen, hingegen am unteren Rand länger und weiter auseinander erscheinen.

Ich hoffe, ich konnte es einigermaßen verdeutlichen und bin zudem hier nicht gänzlich falsch aufgehoben.

Danke für Eure Mühe.
Marcus

Code:
var WIDTH = 400;
var HEIGHT = 300;
var x_start = 100;
var y_start = 0;
var x_linie = 4;
var y_linie = 16;
var x_abstand = 2;
var y_abstand = 8;
 
 
 
window.onload = function() {
 
function init() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  return setInterval(draw, 10);
}
 
function draw () {
 clear();
 context.fillStyle = "#333";
 context.rect(0,0,WIDTH, HEIGHT);
 context.strokeStyle = "#FFFFFF";
 
 context.beginPath();
 context.moveTo(x_start = x_start - x_abstand, y_start = y_start + y_abstand);
 //erzeugt vom Ausgangspunkt den Linienabstand
 
 context.lineTo(x_start = x_start - x_linie, y_start = y_start + y_linie);
 //erzeugt die Linie
 
if ( (y_start < 300) { //Ist Linienhöhe am unteren Rand des canvas, wird wieder zum Ursprungs-Ausgangspunkt gewechselt
 }
 else {
   x_start = 100;
   y_start = 0;
 }
}
init();
 
}
 

Duddle

Posting-Frequenz: 14µHz

AW: Straßenmittelstriche Animiert für HTML5

Ich würde das Problem aus einer anderen Richtung angehen. Im Moment "bewegst" du dein Objekt indem du berechnest wo es beginnt, wo es endet, wie schnell es sich bewegen muss usw.

Eine andere - und meiner Meinung nach bessere - Variante ist die geschickte Kombination von Primitiven, die du dann mithilfe von verschiebst, skalierst und scherst.

Im konkreten Fall: zeichne mental einen 30cm langen, 5cm dicken Strich. Ziehe davon aller 7cm einen 3cm langen Strich ab. Dann fülle alles verbliebene mit einer Farbe. Ergebnis: drei Striche mit jeweils 3cm Abstand, was einem Mittelstreifen grob ähnlich sieht. Ich hoffe du siehst, dass die gesamten festen Werte als Parameter genommen werden können, die (falls animiert) die Illusion von Bewegung hervorrufen können.

Zur Umsetzung solltest du dir die Funktion anschauen.

Sobald du das hast, schau dir den Abschnitt "Transformations" in der an, mit denen du deinen Mittelstreifen dann verschieben und perspektivisch verzerren kannst. Ich vermute, es gibt da (ausserhalb von HTML5) genügend Tutorials, die den Umgang mit Transformationsmatrizen gut erklären, aber konzentrier dich erstmal auf den Mittelstreifen selber.


Duddle
 

IVIrcus

Noch nicht viel geschrieben

AW: Straßenmittelstriche Animiert für HTML5

Moin Duddle und danke für deine Antwort.

Handschriftlich (bei der Arbeit IE 8 ) habe ich mich am ersten Teil versucht. Da ich mich erst seit kurzem mit HTML5 und insb. JS beschäftige, werden da noch semantische Fehler enthalten sein. Bitte um Nachsicht...
(verkürzend hier einmal ohne Interval und document.get... für ein W: 400 H: 200 canvas)

Code:
var start_frei_x = 4;   //start_frei ist der Punkt an dem der Zwischenraum zw. 2 Strichen beginnt
var start_frei_y = -16;  //ist gleichzeitig die Linienlänge der Sichtbaren Linie
var linie_frei_x = 2;   //linie_frei ist der Punkt bis zu welchem der Zwischenraum lang ist
var linie_frei_y = -8;
var x = 50;
var y = 200;
 var i = 0;    // i ist der Zähler für 4 Durchläufe (4/4 Bildzustände gibt es)
 
c.beginPath();
c.moveTo(100,0);
c.lineTo(x, y);                                                            //durchgehende Linie
c.globalCompositeOperation = "source-out";             // alles hiernach wird von Linie abgezogen
c.moveTo(x = x + start_frei_x, y = y + start_frei_y);  //gehe zum ersten Startpunkt
c.lineTo(x = x + linie_frei_x, y = y + linie_frei_y);      //ziehe Pfad für ersten freien Bereich
.... //c.moveTo und c.lineTo x 8 , wäre sicherlich ein Fall für die For-Schleife
 
i++;  
 
if (i <=3) {                                             // 4 x mal soll wie folgt verschoben werden ...
start_frei_x = start_frei_x -1;                 // ist ein Viertel der sichtbaren Linie
start_frei_y = start_frei_y +4;
}
else {
i = 0;            // wieder von vorne
x = 50;
y = 200;
}

Meintest du das so? Zumindest mit etwas gutem Willen? :)

Vielen Dank nochmal für deine Hilfe und die ausführliche Antwort.
 

Duddle

Posting-Frequenz: 14µHz

AW: Straßenmittelstriche Animiert für HTML5

Dein Stil zeigt, dass du nicht oft programmierst. Das ist kein Problem, schließlich ist das Forum für alle Level von Nutzern gedacht.

Erstens: Berechnungen der Art "aller x vielen Runden will ich wieder von vorn beginnen" ist ein klassischer Anwendungsfall für Modulo-Berechnungen. In JavaScript ist das Prozentzeichen % der Modulo-Operator. Beispiel:
HTML:
var i = 0;
for(...) {
  i = (i+1) % 4;
  alert(i);
}
Hier läuft i von 0 bis 3, zurück zu 0, wieder bis 3 usw. Das ist gleichbedeutend mit und offensichtlich kürzer als:
HTML:
var i = 0;
for(...) {
  i = i++;
  alert(i);
  if(i > 3) {
    i = 0;
  }
}

Zweitens: Ich empfehle dir, Zuweisungen nicht in Funktionsaufrufen auszuführen, wie z.B.
HTML:
c.moveTo(x = x + start_frei_x, y = y + start_frei_y);
Sehr viel übersichtlicher ist
HTML:
x = x + start_frei_x;
y = y + start_frei_y;
c.moveTo(x, y);
Das sind zwar zwei Zeilen mehr, aber ich kann viel schneller auffassen was moveTo übergeben wird.

Wie sieht dein Ergebnis denn mittlerweile aus? Ist es so erstmal richtig?


Ich zeige mal, was ich probehalber geschrieben habe. Mein Ansatz war mit echten Vierecken (einfach nur so), aber die Logik ist natürlich die gleiche:
HTML:
var lWidth = 30;
var mittelPunkt = WIDTH/2-lWidth/2;
ctx.globalCompositeOperation='source-over';
ctx.fillStyle="#FF0000";
ctx.fillRect(mittelPunkt,0,lWidth,HEIGHT);
Das zeichnet den Ausgangsstrich.

Um einen statischen "Durchbruch" zu erhalten, zeichne ich ein Rechteck an den Anfang.
HTML:
ctx.globalCompositeOperation='destination-out';
var lHeight = 50;
ctx.fillRect(mittelPunkt,0,lWidth,lHeight);
Um das Ding zu bewegen, variiere ich die Ausgangsposition von y und lasse sie von 0 bis Höhe des canvas laufen.
HTML:
ctx.globalCompositeOperation='destination-out';
var lHeight = 50;
dy = (dy + 10) % HEIGHT; // var dy wurde ausserhalb dieser Funktion definiert, d.h. global
ctx.fillRect(mittelPunkt,dy,lWidth,lHeight);
Jetzt startet das Ding aber schon komplett im Bild, also muss ich es im negativen starten lassen und etwas weiter schieben als vorher:
HTML:
ctx.globalCompositeOperation='destination-out';
var lHeight = 50;
dy = (dy + 10) % (HEIGHT+lHeight);
ctx.fillRect(mittelPunkt,dy-lHeight,lWidth,lHeight);
Jetzt läuft das Ding schon ohne Unterbrechung durch. Um jetzt mehrere davon zu machen, kann ich es natürlich kopieren und mit etwas Mathe dafür sorgen, dass die sich sauber überschneiden. Der Ansatz ist aber meiner Meinung nach nicht besonders hübsch, deshalb habe ich es anders gemacht.

Jede der Freistellen beginnt aller lAbstand Pixel und ist jeweils lHeight Pixel groß. Ich brauche mindestens so viele Freistellen, dass ich die ganze Höhe abdecke, plus ein bisschen mehr für die Übergänge. Sobald die erste Freistelle sich bis zum Anfangspunkt der zweiten Freistelle bewegt hat, geht es wieder von vorn los. Der Code dafür ist dann:
HTML:
dy = (dy+5) % lAbstand;
for(var y = 0; y <= HEIGHT; y += lAbstand) {
    var sy = y + dy;
    ctx.fillRect(mittelPunkt,sy-lHeight,lWidth,lHeight);
}
Im ersten Zustand sieht das also so aus (für HEIGHT=500, lAbstand=200, lHeight=50):
Code:
dy ist anfangs 0;
freistelle nummer 	sy 	sy-lHeight
1 (y = 0)		0 	-50 //also noch nicht im Bild
2 (y = 200) 		200 	150
3 (y = 400) 		400 	350
(danach ist y = 600, damit größer als HEIGHT, also wird die Schleife beendet)
Im direkt folgenden Frame:
Code:
dy ist jetzt 5; //entspricht der Geschwindigkeit
freistelle nummer 	sy 	sy-lHeight
1 (y = 0)		5 	-45 //jetzt mit 5 Pixeln im Bild
2 (y = 200) 		205 	155
3 (y = 400) 		405 	355
Ein paar Frames später kommt der Übergang, wenn dy 5 einen Schritt vor lAbstand ist, in diesem Fall lAbstand-5 = 195:
Code:
dy ist jetzt 195; //entspricht der Geschwindigkeit
freistelle nummer 	sy 	sy-lHeight
1 (y = 0)		195 	145 
2 (y = 200) 		395 	345
3 (y = 400) 		595 	545 //ist schon seit 9 Frames nicht mehr zu sehen
Jetzt solltest du sehen, dass es der nächste Schritt das gleiche Ergebnis ist wie im 0ten Frame. Die erste Freistelle "rutscht" zu sy=200 und entspricht damit der zweiten Freistelle im 0ten Frame, etc.

Laaaaange Rede: ein bisschen Mathe und vorallendingen der nette Modulo-Operator lösen dieses Problem sehr simpel.


Das schwierige jetzt ist die Transformation, bisher werden hier zumindest meine Linien nur gerade gezeichnet. Aber ich habe ja verlinkt, welche Möglichkeiten es da theoretisch gibt.


Duddle
 

IVIrcus

Noch nicht viel geschrieben

AW: Straßenmittelstriche Animiert für HTML5

Hey Duddle,

dann brauche ich mich ja nicht mehr verstellen :)
Danke für die Wahnsinns Antwort. Morgen werde ich mich da wieder ranmachen können.

Ich bin mal gespannt, ob ich dir folgen kann ...
Grüße
 

IVIrcus

Noch nicht viel geschrieben

AW: Straßenmittelstriche Animiert für HTML5

Hey Duddle,

entschuldige meine späte Antwort. Ein wenig Zeit musste ich mir dann doch dafür nehmen :rolleyes:

Nun habe ich es bis zur Transformation umgesetzt und wollte dir das mitteilen.

Da ich tatsächlich weniger in den sieben Meeren des JavaScripts segle, fällt mir das doch schon etwas schwerer. Insbesondere, da es oft vor kommt, dass mir Fehler in der Semantik unterlaufen, die ich dann lange suche. :uhm:

Jetzt hoffe ich auf die Transformation und bin mir sicher, dass es wieder eine Weile dauern wird. Dir trotzdem vielen Dank für deine klasse Erklärungen.

Grüße
Marcus
 

IVIrcus

Noch nicht viel geschrieben

AW: Straßenmittelstriche Animiert für HTML5

Fürs Erste habe ich übrigens anstatt einer "fillRect"-Linie ein schräges "lineTo" mit einer "width" von 20-30 verwendet. Verbreiter ich jetzt die Masken-"fillRects", dann habe ich zumindest schon einen annähernd guten Effekt der seitlichen Betrachtung. (Es fehlt natürlich noch der Effekt, dass es im Horizont enger und schmaler wird).

Und auch hier erkennt man wieder: Es war nicht deine Idee ;)
 
Bilder bitte hier hochladen und danach über das Bild-Icon (Direktlink vorher kopieren) platzieren.
Antworten auf deine Fragen:
Neues Thema erstellen

Willkommen auf PSD-Tutorials.de

In unseren Foren vernetzt du dich mit anderen Personen, um dich rund um die Themen Fotografie, Grafik, Gestaltung, Bildbearbeitung und 3D auszutauschen. Außerdem schalten wir für dich regelmäßig kostenlose Inhalte frei. Liebe Grüße senden dir die PSD-Gründer Stefan und Matthias Petri aus Waren an der Müritz. Hier erfährst du mehr über uns.

Stefan und Matthias Petri von PSD-Tutorials.de

Nächster neuer Gratisinhalt

03
Stunden
:
:
25
Minuten
:
:
19
Sekunden

Flatrate für Tutorials, Assets, Vorlagen

Zurzeit aktive Besucher

Statistik des Forums

Themen
118.565
Beiträge
1.538.067
Mitglieder
67.488
Neuestes Mitglied
Andrew56524
Oben