JavaScript-Animation, die funktioniert (Teil 4 von 4)

Im ersten Teil dieser Serie haben wir die Idee der Verwendung eingeführt Sprit als einfache, browserübergreifende Möglichkeit, interaktive Animationen für das Web zu erstellen. Im zweiten Teil haben wir einige Animationen zum Laufen gebracht, und im dritten Teil haben wir unseren Code aufgeräumt und für das Web vorbereitet.

Einführung

Heute, in unserem letzten Teil, gehen wir durch das Setup Eventhandler Anstatt auf angeklickte Schaltflächen zu reagieren, folgen unsere Roboter der Maus auf dem Bildschirm. Dabei werden wir auch darüber sprechen, dass der Code browserübergreifend und der Touchscreen aktiviert wird.

Wenn Sie einen Blick auf unseren Code vom letzten Mal werfen, werden Sie feststellen, dass der Code zwar gut ausgeführt wird (und mit mehreren Robotern), aber es keine einfache Möglichkeit gibt, den Code auszuführen.

Event-Handler

Event-Handler sind Befehle, die bestimmten Code ausführen, wenn bestimmte Ereignisse ausgelöst werden. Zum Beispiel könnten Sie haben my_function () Wird ausgeführt, wenn ein Benutzer auf Ihr klickt div mit der id 'my_div'. Oder du hättest my_other_function () Immer ausführen, wenn ein Benutzer die Maus darüber bewegt 'my_other_div'.

Theoretisch ist dies eine ziemlich einfache und unkomplizierte Idee. Wenn Sie verschiedene Browser eingebunden haben, kann dies leider etwas verwirrend werden. In einer idealen Welt würde jeder Webbrowser denselben Code und HTML-Code auf dieselbe Weise interpretieren, und Entwickler würden einmalig Code schreiben, der für jeden Benutzer gleich wäre. In der realen Welt können verschiedene Browser völlig unterschiedliche Befehle haben, um dasselbe zu tun (* Husten * * Husten * Internet Explorer), und manchmal versucht man, ein einziges Stück Code zu bekommen, damit alle Browser das Gefühl haben, Katzen zu hüten. In letzter Zeit wurde die Situation viel besser, da Chrome, Firefox, Safari und Opera alle sehr ähnlich auf Code reagieren. Internet Explorer 9 und 10 entsprechen weitaus mehr Standards als frühere Versionen, und fast niemand verwendet Internet Explorer 7 oder 6 mehr. Daher erhalten wir für unseren Code Event-Handler für moderne Browser und Internet Explorer 8.

Als Randbemerkung ist dies ein Fall, in dem es sich wirklich lohnt, eine robuste JavaScript-Bibliothek wie jQuery zu verwenden. jQuery erledigt die gesamte Arbeit für Sie beim Cross-Browser-Testen. Sie müssen also nur einen Befehl eingeben. Die jQuery-Bibliothek übersetzt ihn für jeden Browser hinter den Kulissen. Darüber hinaus sind viele Befehle in jQuery intuitiver und einfacher als das Kern-JavaScript.

Aber da ich stur bin und dies eine Lerngelegenheit ist, werden wir den harten Weg fortsetzen und dies alles nur mit JavaScript und ohne Abhängigkeiten tun!

Seiteninteraktion

Unser erster Schritt besteht also darin, zu entscheiden, wie genau wir mit der Seite interagieren möchten. Wenn ich mit der Maus über den Bühnenbereich fahre, möchte ich, dass alle Roboter zur Maus laufen. Wenn sie die Maus erreichen oder wenn sich die Maus direkt über ihnen befindet, möchte ich, dass sie nicht mehr laufen. Wenn die Maus sie überquert, möchte ich, dass sie springen. Wenn die Maus den Bühnenbereich verlässt, möchte ich, dass sie nicht mehr laufen. Wir fangen mit dem Anhängen dieser Ereignisse in der RobotMaker Funktion:

 stage.addEventListener ('mousemove', stage_mousemove_listener, false); robot.addEventListener ('mouseover', robot_mouseover_listener, false); stage.addEventListener ('mouseout', stage_mouseout_listener, false);

In den obigen Zeilen haben wir gesagt, dass immer, wenn der Benutzer die Maus innerhalb des Bühnenelements bewegt, eine aufgerufene Funktion ausgelöst wird stage_mousemove_listener () (Beachten Sie, dass wir die Klammern nicht in den Befehl aufnehmen). Wenn der Benutzer die Maus über das Roboterelement bewegt, wird dies ebenfalls ausgelöst robot_mouseover_listener (), Wenn der Benutzer die Maus außerhalb der Bühne bewegt, wird er ausgelöst stage_mouseout_listener ().

Wie bereits erwähnt, verfügt Internet Explorer 8 und darunter leider über einen (ähnlichen, aber unterschiedlichen) Befehl, um dasselbe zu tun. Daher müssen wir testen, welchen Befehl der Browser des Benutzers versteht und wie diese Methode ausgeführt wird.

 if (stage.addEventListener) // Wir werden prüfen, ob dieser Befehl verfügbar ist stage.addEventListener ('mousemove', stage_mousemove_listener, false); robot.addEventListener ('mouseover', robot_mouseover_listener, false); stage.addEventListener ('mouseout', stage_mouseout_listener, false);  else // Wenn nicht, müssen wir IE-Befehle verwenden. stage.attachEvent ('onmousemove', stage_mousemove_listener); robot.attachEvent ('onmouseover', robot_mouseover_listener); stage.attachEvent ('onmouseout', stage_mouseout_listener); 

Möglicherweise stellen Sie fest, dass das Format der Befehle sehr ähnlich ist, jedoch einige wesentliche Unterschiede besteht 'addEventListener' während der andere sagt 'attachEvent'. Man sagt "mousemove" während der andere sagt 'onmousemove'. Einer benötigt einen dritten Parameter, während der andere nur zwei Parameter verwendet. Wenn Sie eines dieser Elemente mischen, wird der Befehl nicht ausgeführt. Dies sind die Arten von Dingen, bei denen Sie den Kopf gegen die Wand schlagen wollen. Leider ist dies nicht das Ende der zusätzlichen Codierung, die wir für die browserübergreifende Funktion durchführen müssen.

Hörfunktionen

Als nächstes schreiben wir die Hörfunktionen. Wir beginnen mit der Funktion, die ausgelöst wird, wenn der Benutzer die Bühne überquert. Da das ein ist mousemove Listener, diese Funktion wird jedes Mal ausgelöst, wenn die Maus innerhalb des Bühnenbereichs bewegt wird (dh sie wird mehrmals pro Sekunde ausgelöst, während sich die Maus bewegt). Diese Funktion muss den Standort des Roboters mit dem Standort der Maus vergleichen und den Roboter dazu veranlassen, sich entsprechend zu verhalten. Jedes Mal, wenn die Funktion ausgelöst wird, wird geprüft, ob der Roboter die gleiche Richtung weiterlaufen oder das Verhalten ändern muss. Es muss also so etwas sein:

 // Innerhalb von RobotMaker // Wir müssen einige zusätzliche Variablen einführen, um var mouseX zu verfolgen. // Zum Verfolgen der horizontalen Mausposition var running_dir = "; // Zum Verfolgen, ob (und wo) der Roboter gerade var stageOffset ausführt; // Zum Verfolgen der Position der Bühnenfunktion stage_mousemove_listener (e) // Finden Sie die horizontale Position von die Maus innerhalb der Bühne… // Diese Position wird in 'mouseX' gespeichert. // Dann vergleichen wir 'mouseX' mit dem Roboter und entscheiden, ob wir anders laufen müssen, wenn (((robot.offsetLeft + (15 * run_speed.) )) < (mouseX - robot.offsetWidth)) && running_dir !== 'r' && (!jump_timer || jump_timer === undefined)) // If the mouse is in the stage and to the right of the robot, make run right, if not already running_dir = 'r'; clearTimeout(run_timer); run_r(1, robot.offsetLeft);  else if ((mouseX < robot.offsetLeft - (15 * run_speed)) && running_dir !== 'l' && (!jump_timer || jump_timer === undefined))  // If the mouse is in the stage and to the left of the robot, make run left, if not already running_dir = 'l'; clearTimeout(run_timer); run_l(1, robot.offsetLeft);  else if ((robot.offsetLeft < mouseX) && ((robot.offsetLeft + robot.offsetWidth) > mouseX) && running_dir! == "&& (! jump_timer || jump_timer === undefined)) // Wenn sich die Maus im Stadium und über einem Roboter befindet, stoppen und löschen Sie running_dir running_dir ="; clearTimeout (run_timer); if (face_right) robot.style.backgroundPosition = "0px 0px";  else robot.style.backgroundPosition = "0px -50px";  // Wenn keine der obigen Aussagen zutrifft, lassen wir unser aktuelles Verhalten fortfahren.

Also, in der Funktion oben, sobald wir finden können mouseX, Wir vergleichen es mit dem Standort des Roboters und lösen oder lösen die verschiedenen Lauffunktionen nach Bedarf aus. Leider finden mouseX ist ein bisschen schwierig, da die Mausposition eine andere Sache ist, die verschiedene Browser unterschiedlich machen. Anstelle von (komplizierteren) und langwierigen Erklärungen wird hier die Cross-Browser-Methode zum Auffinden verwendet mouseX, inspiriert aus dem exzellenten Quirksmode-Blog (der eine großartige Quelle für fortgeschrittenes JavaScript-Lernen ist).

 Funktion stage_mousemove_listener (e) var posX = 0; if (! e) var e = window.event;  if (e.pageX) posX = e.pageX;  else if (e.clientX) posX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;  mouseX = posX - stageOffset.xpos; // Und wir finden mouseX! 

Wir haben ein Argument aufgerufen e in der Funktion, obwohl wir nichts weitergeben. Da dies ein Ereignis-Listener ist, kann eine automatische Variable aufgerufen werden e das speichert Ereignisinformationen wie Mausdaten. Da unterschiedliche Browser dies jedoch unterschiedlich speichern, müssen wir viele zusätzliche Schritte hinzufügen.

Wir finden endlich mouseX durch das Finden posX (Dies ist die x-Position der Maus auf der Seite) und subtrahieren Sie, wie weit die Bühne von der äußersten linken Seite der Seite entfernt ist (gespeichert in stageOffset.xpos). Dies gibt uns an, wie weit vom linken Rand der Bühne entfernt sich die Maus befindet, mit der wir direkt vergleichen können robot.offsetLeft. Da die Bühne je nach Layout auf der Seite unterschiedlich angeordnet sein kann, müssen wir auch den exakten Pixelversatz der Bühne ermitteln, damit die Funktion genau ist, und diese Informationen in speichern stageOffset. Glücklicherweise gibt es einen hübschen Trick, mit dem wir den absoluten Offset eines Elements mit dieser Funktion aus dem Blog von Vishal Astik finden können.

 // In RobotMaker var x = 0; var y = 0; Funktion find_stage_offset (el) x = el.offsetLeft; y = el.offsetTop; el = el.offsetParent; while (el! == null) x = parseInt (x) + parseInt (el.offsetLeft); y = parseInt (y) + parseInt (el.offsetTop); el = el.offsetParent;  return xpos: x, ypos: y;  var stageOffset = find_stage_offset (stage);

Nun, da haben wir das geschrieben mousemove Zuhörer werden die anderen sein viel einfacher. Für den Roboter Mouseover Zuhörer, wir müssen nur überprüfen, ob der Roboter bereits springt, und wenn nicht, stoppen Sie den Lauftimer und lassen Sie ihn springen.

 function robot_mouseover_listener () if (! jump_timer || jump_timer === undefined) clearTimeout (run_timer); jmp (wahr, robot.offsetTop); 

Das Mouseout Zuhörer ist auch ziemlich einfach. Wir müssen nur einige unserer Variablen zurücksetzen, die wir zur Verfolgung des Roboters verwenden. Wenn der Roboter nicht springt, bringen Sie den Roboter zum stehenden Sprite zurück.

 Funktion stage_mouseout_listener () mouseX = undefined; running_dir = "; if (! jump_timer || jump_timer === undefined) clearTimeout (run_timer); if (face_right) robot.style.backgroundPosition =" 0px 0px "; else robot.style.backgroundPosition =" 0px - 50px ";

Animationsfunktionen

Die Funktionen, die die Lauf- und Sprungbewegungen animieren, haben sich diesmal nicht wesentlich geändert. Wir haben gerade die Tracking-Variable hinzugefügt running_dir, die Aussage herausgenommen, die prüft, ob der Roboter kurz vor der Wand steht (da dies bei unserem System überflüssig ist) Mouseout function), und fügen Sie der Sprungfunktion ein wenig Code hinzu, die erneut prüft, ob der Roboter gestartet werden soll, wenn sich die Maus innerhalb der Stufe befindet, nachdem sie nach einem Sprung gelandet ist. Hier ist der endgültige Code (ziemlich groß):

 Funktion run_r (Phase, links) face_right = true; running_dir = 'r'; if ((links + (15 * Laufgeschwindigkeit)) < (mouseX - robot.offsetWidth)) // if mouse is to the right, run left = left + (15 * run_speed); robot.style.left = left+"px"; switch (phase) case 1: robot.style.backgroundPosition = "-40px 0px"; run_timer = setTimeout(function()run_r(2, left);, 200); break; case 2: robot.style.backgroundPosition = "-80px 0px"; run_timer = setTimeout(function()run_r(3, left);, 200); break; case 3: robot.style.backgroundPosition = "-120px 0px"; run_timer = setTimeout(function()run_r(4, left);, 200); break; case 4: robot.style.backgroundPosition = "-80px 0px"; run_timer = setTimeout(function()run_r(1, left);, 200); break;   else if ((left + (15 * run_speed)) < mouseX)  // if mouse if above, stop robot.style.backgroundPosition = "0px 0px"; running_dir =";  else  // if mouse is to the left, run left running_dir = 'l'; run_l(1, robot.offsetLeft);   function run_l(phase, left) face_right = false; running_dir = 'l'; if (mouseX < robot.offsetLeft - (15 * run_speed)) // if mouse is to the left, run left = left - (15 * run_speed); robot.style.left = left+"px"; switch (phase) case 1: robot.style.backgroundPosition = "-40px -50px"; run_timer = setTimeout(function()run_l(2, left);, 200); break; case 2: robot.style.backgroundPosition = "-80px -50px"; run_timer = setTimeout(function()run_l(3, left);, 200); break; case 3: robot.style.backgroundPosition = "-120px -50px"; run_timer = setTimeout(function()run_l(4, left);, 200); break; case 4: robot.style.backgroundPosition = "-80px -50px"; run_timer = setTimeout(function()run_l(1, left);, 200); break;   else if (mouseX < (robot.offsetLeft + robot.offsetWidth - (15 * run_speed))) // if mouse overhead, stop robot.style.backgroundPosition = "0px -50px"; running_dir =";  else  // if mouse is to the right, run right running_dir = 'r'; run_r(1, robot.offsetLeft);   function jmp(up, top) running_dir ="; if (face_right) robot.style.backgroundPosition = "-160px 0px";  else  robot.style.backgroundPosition = "-160px -50px";  if (up && (robot.offsetTop > (20 * (1 / Sprunghöhe)))) top = top - (top * 0,1); robot.style.top = top + "px"; jump_timer = setTimeout (function () jmp (nach oben, oben);, 60);  else if (up) up = falsch; jump_timer = setTimeout (function () jmp (nach oben, oben);, 60);  else if (! up && (robot.offsetTop.) < 115)) top = top + (top * 0.1); robot.style.top = top+"px"; jump_timer = setTimeout(function()jmp(up, top);, 60);  else  robot.style.top = "120px"; if (face_right) robot.style.backgroundPosition = "0px 0px";  else  robot.style.backgroundPosition = "0px -50px";  jump_timer = false; if (mouseX !== undefined) if (((robot.offsetLeft + (15 * run_speed)) < (mouseX - robot.offsetWidth)) && running_dir !== 'r') // make run right, if not already running_dir = 'r'; clearTimeout(run_timer); run_r(1, robot.offsetLeft);  else if ((mouseX < robot.offsetLeft - (15 * run_speed)) && running_dir !== 'l')  // make run left, if not already running_dir = 'l'; clearTimeout(run_timer); run_l(1, robot.offsetLeft);    

Jetzt haben wir unsere neu geschriebenen Funktionen, die für alle Browser hervorragend geeignet sind, es sei denn, diese Browser verfügen über Berührungseingaben. Wir haben noch ein bisschen mehr zu tun, damit unsere Roboter alles laufen lassen können. Da sich Touchscreens etwas anders verhalten, müssen wir unsere Event-Listener zusätzlich codieren.

Unterstützende Touchscreens

Wir müssen einige neue Regeln für Touchscreens festlegen: Wenn der Bildschirm an einer beliebigen Stelle der Bühne berührt wird, läuft der Roboter zu dieser Stelle, bis der Finger angehoben wird. Wenn der Benutzer den Roboter berührt, springt der Roboter. Zunächst werden wir unserer früheren Funktion einige zusätzliche Touch-Event-Handler hinzufügen, und wir werden den Code so schreiben, dass er bei jedem Aufruf automatisch ausgeführt wird RobotMaster Funktion wird aufgerufen.

 (function () if (stage.addEventListener) stage.addEventListener ('touchstart', stage_mousemove_listener, false); stage.addEventListener ('touchmove', stage_mousemove_listener, false); stage.addEventListener (). stage.addEventListener ('mousemove', stage_mousemove_listener, false); robot.addEventListener ('mouseover', robot_mouseover_listener, false); stage.addEventListener ('mouseout', stage_mouseout_listener, false); , stage_mousemove_listener); robot.attachEvent ('onmouseover', robot_mouseover_listener); stage.attachEvent ('onmouseout', stage_mouseout_listener);) ();

Wir müssen uns keine Sorgen darüber machen, dass die Touch-Listener im Internet Explorer 8-Format vorliegen. Wenn ein Gerät keine Touch-Unterstützung hat, werden die Listener ignoriert. Jetzt müssen wir das aktualisieren stage_mousemove_listener () verhalten sich anders, wenn der Browser berührungsfähig ist.

 function stage_mousemove_listener (e) / * * Zuerst prüfen wir, ob es sich um ein Touchscreen-Gerät handelt (wenn es e.touches hat) * / if (e.touches) e.preventDefault (); // wir möchten das abbrechen, was der Browser normalerweise tun würde, wenn er dort berührt würde // Wenn die Berührung innerhalb der Bühnengrenzen war ... if ((e.touches [0] .pageX> stageOffset.xpos) && (e.touches [ 0] .pageX < (stageOffset.xpos + stage.offsetWidth)) && (e.touches[0].pageY > stageOffset.ypos) && (e.touches [0] .pageY < (stageOffset.ypos + stage.offsetHeight))) // we set the mouseX to equal the px location inside the stage mouseX = e.touches[0].pageX - stageOffset.xpos;  else  // if the touch was outside the stage, we call the mouseout listener stage_mouseout_listener();  /* * If the touch is directly on the robot, then we stop the run timer and make the robot jump */ if ((e.touches[0].pageX > robot.offsetLeft) && (e.touches [0] .pageX < (robot.offsetLeft + robot.offsetWidth)) && (e.touches[0].pageY > (stageOffset.ypos + stage.offsetHeight - robot.offsetHeight)) && (e.touches [0] .pageY < (stageOffset.ypos + stage.offsetHeight)) && (!jump_timer || jump_timer === undefined)) clearTimeout(run_timer); jmp(true, robot.offsetTop);   else  // Finding the mouseX for non-touch devices… // All of our non-touch device code here  

Sie stellen möglicherweise fest, dass wir keine "Türen" mehr in unserem haben RobotMaker Funktion, aber da wir unseren gesamten Code mit Event-Handlern aufrufen, die wir innen zuweisen RobotMaker, wir brauchen sie nicht mehr! Sowohl für unsere Bühne als auch für unsere Charaktere möchten wir etwas CSS speziell für Touch-Geräte hinzufügen, damit nicht versucht wird, Bilder auszuschneiden und einzufügen, wenn ein Benutzer einen Finger darauf hält.

 #stage, .character -webkit-user-select: none; 

Und schließlich werden wir alle unsere Roboter am unteren Rand der Seite deklarieren. Sie verwenden dasselbe Format wie unsere Event-Handler-Funktion, damit der Code beim Laden der Seite automatisch ausgeführt wird. Diese Methode verhindert auch, dass diese Roboterobjekte globale Variablen sind Die einzige globale Variable, die wir in diesem gesamten Skript haben, ist die RobotMaker () Funktion.

 (Funktion () var j = RobotMaker (document.getElementById ('j'), 1, 1); var j2 = RobotMaker (document.getElementById ('j2'), .8, 5); var j3 = RobotMaker (Dokument .getElementById ('j3'), 1.1, .5); var j4 = RobotMaker (document.getElementById ('j4'), .5, .75);) ();

Bitte überprüfen Sie das Endergebnis in seiner ganzen Pracht!

Fazit

Ich empfehle Ihnen dringend, den gesamten (und vollständig kommentierten!) Code zu studieren, und Sie können hier auch alle vier Roboter-Sprites herunterladen.

Viel Spaß beim Animieren!