Author: Steven Riche
Release time: 2014 21 months 18
Original link: http://code.tutsplus.com/tutorials/javascript-animation-that-works-part-4-of-4--net-35263
Translation: Sub-yi---------will javascript to do exactly
Break two sentences
Toss for one months. Assorted things together. It's awful.
Blog has been stopped for about one months, from today on everything is new, do yourself OK
----------------------------------------------------------------------------------------------
In this series of
p=35205 "> The first article, we introduced the use of sprites to create simple, cross-browser interactive animations on the web. In the second article, we made the animation work, and in the third article, we tidied up our code and prepared it for use on the web
Introduced
Now, in our final installment, we're going to be moving with the mouse on the screen by creating an event handler rather than a response from the robot when the button is clicked.
In the process. We'll talk about cross-browser code, and the touchscreen is also available
If you look at our last code. You can see that while our code executes very well (and there are multiple robots at the same time), there is no simple way to execute the code.
Event handlers
An event handler is a command that tells some code to run when a particular event is triggered. For example, whenever you can have a user click on the ' div ' with the ' my_div ' ID,' my_function () ' runs.
Or, when the user moves the mouse on ' My_other_div ' . ' my_other_function () ' run
Theoretically, this is a fairly simple and intuitive idea. Unfortunately, when you get involved in different browsers, it's a bit confusing. Ideally, each browser would interpret the code in the same way, and the developer would simply write the code once to allow each user to see the same result. In the real world, different browsers may have completely different names to do the same thing (* cough * IE), so sometimes you want a piece of code to be executed in all browsers. It makes people think it's like herding a bunch of cats. Recent. The situation has become very good, Chrome,firefox, Safgari,opera's response to the code has been very similar, IE9 and IE10 have become more compliant than earlier version numbers. And almost no one was using IE7 and IE6. Therefore, our code will enable event handlers in modern browsers and IE8 species to work
As a description on the one hand. This is a reason to use a powerful JavaScript library, such as jquery.
jquery has done all the cross-browser testing for you, so you just need to enter a command, and jquery will translate it behind the scenes to make it available in every browser. In addition, many jquery commands are more intuitive and straightforward than core JavaScript.
However, because of my stubborn, and this is a learning opportunity, we will continue to work on this difficult road, just use JavaScript to do all this, do not rely on whatever library
Page interaction
Our first step is to decide exactly how to interact with the page.
When I move the mouse over the stage area. I want all the robots running in the direction of the mouse movement. When they reach the mouse or mouse just above them, I want them to stop moving. If you put the mouse on them, I want them to jump up.
Finally, when the mouse leaves the stage, I want them to stop running. We will start from the binding event to the inside of the robotmaker function.
Stage.addeventlistener (' MouseMove ', Stage_mousemove_listener, false); Robot.addeventlistener (' MouseOver ', robot_ Mouseover_listener, False); Stage.addeventlistener (' Mouseout ', Stage_mouseout_listener, false);
So. In the previous lines of code, we said that whenever the user moves the mouse over the stage element. Will trigger a callStage_mousemove_listener ()The function (note. In the command. We did not include the number of references). Similarly, when the user moves the mouse over the robot element. Will TriggerRobot_mouseover_listener ()When the user moves the mouse off the stage, triggeringStage_mouseout_listenr ()
Unfortunately, as we mentioned before, IE8 and its lower version use different (but similar) commands to do the same thing, so we need to test it. To know which command the user's browser will understand and run the corresponding method.
if (Stage.addeventlistener) {//We'll test to see if the This command is available stage.addeventlistener (' MouseMove ', s Tage_mousemove_listener, false); Robot.addeventlistener (' mouseover ', Robot_mouseover_listener, false); Stage.addeventlistener (' mouseout ', Stage_mouseout_listener, false);} else {//If not, we had to use IE commands stage.attachevent (' onmousemove ', stage_mousemove_listener); Robot.attachevent (' onmouseover ', robot_mouseover_listener); Stage.attachevent (' onmouseout ', stage_mouseout_listener); }
You may notice that the format of those commands is very similar. But there are some basic differences: one is called ' AddEventListener ', one is called ' attachevent ', one is called ' MouseMove ', but there is a ' onmousemove '. One requires a third parameter. And the other one just used two.
Confusing whatever one of them will cause the command not to run. This series of things will make you use your head to wall the impulse. Unfortunately, in order to be capable of cross-browser, this is not the last code that we need to write extra
Listener functions
Next, we'll write the listener function.
Start by writing a function that triggers the user to move on the stage.
Because it is a mousemove listener, it will trigger each time the mouse moves within the stage area (which means that it will trigger multiple times in a second) This function needs to compare the position of the robot with the position of the mouse. And make the robot play by ear. Each time the function is triggered, it will check that the robot needs to continue running in the same direction. or transform it into other behaviors.
Therefore, it needs to be written as follows.
Inside of Robotmaker//We'll need to introduce a few extra variables to Trackvar mousex; For tracking horizontal mouse positionvar Running_dir = '; For tracking if (and where) robot is currently Runningvar Stageoffset; For tracking the position of the stage function Stage_mousemove_listener (e) {//Find the horizontal position of the Mouse inside of the stage ...//That position would be is saved in ' mousex '//Then we compare ' MouseX ' to the robot, and decide if we need to run differently if (((Robot.offsetleft + (Run_speed) <) amp;& running_dir!== ' R ' && (!jump_timer | | jump_timer = = undefined)) {//If the mouse is in the stage a nd 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-(run_speed)) && running_dir!== ' l ' && (!jump_timer | | jum P_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) && runni Ng_dir!== ' && (!jump_timer | | jump_timer = = undefined)) {//If the mouse is in the stage and over a robot, Stop and clear running_dir running_dir = '; Cleartimeout (Run_timer); if (face_right) {robot.style.backgroundPosition = "0px 0px"; } else {robot.style.backgroundPosition = "0px-50px"; }}//If None of the above is true and then we-let we behavior continue}
In the function above. Once we findMouseX, we can compare the position of the robot and, if necessary, trigger or stop different running functions.
Unfortunately, finding mousex is a bit tricky, because the mouse position is something different than a different browser.
A complex and lengthy explanation to avoid finding mousex . Just as inspired by the excellent Quirksmode blog (this is a great source of learning a lot of other advanced JavaScript technologies):
function 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; We found mousex!. }
We have a parameter called E in the function, although we do not pass whatever thing to it. But this is an event listener, and we will take the initiative to have a variable called E, which stores information related to events, such as mouse data. However, different browsers store different ways, we have to add an additional step.
We finally foundPosX(the mouse's horizontal coordinate on the page) and subtract the value of the page from the left side of the stage (stored inStageoffset.xpos), and then findMouseX, which gives us the distance from the left edge of the stage of the mouse, and we can use it directly andRobot.offsetleftTo make a comparative comparison. Depending on the layout, the stage may be in a different location, and we need to find the exact pixel offset of the stage and store it inStageoffsetIn Fortunately, we were able to use a clever gimmick to find the absolute offset of the element, a function from Vishal Astik's blog
Within robotmaker var x = 0;var y = 0;function 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);
And now we've written it all.MouseMoveListeners, others will be much more easy.
For the robot mouseover Listener, we just need to detect if the robot is jumping, assuming it is not, stop running and make it jump.
function Robot_mouseover_listener () { if (!jump_timer | | jump_timer = = = undefined) { cleartimeout (run_timer); JMP (True, robot.offsettop);} }
mouseoutListeners are the same and very easy. Just need to reset some of the variables we use to track robot, and if the robot doesn't jump, set the robot as a standing elf.
function 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";}} }
Animation functions
This time. The run-and-jump motion function does not change very much. We just added some tracking variables.Running_dir, removing the robot is going to hit the strong statement (as this ismouseoutThe redundancy of the function. and add some code to the jump function, it is used to check again, if the mouse is still in the stage, when the robot falls after jumping. Whether it needs to start running. The following is the last code (quite large):
function Run_r (phase, left) {face_right = true; Running_dir = ' R '; if (left + (run_speed)) < (mousex-robot.offsetwidth)) {//If mouse are to the right and run left = Left + (* 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 + (run_speed)) < MouseX) {//If mouse if above, stop robot.style.backgroundPosition = "0px 0 PX "; Running_dir = ";} ElSE {//If mouse is to the left and 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-(run_speed)) {//If mouse is to the left and run left = left-(* run_spee D); 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-(run_speed)) {//If mouse overhead, stop robot.style.backgroundPosition = "0px-50px"; Running_dir = ";} else {//If mouse is to the right and 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 > (1/jump_height))) {top = top-(top * 0.1); Robot.style.top = top+ "px"; Jump_timer = SetTimeout (function () {JMP (up, top);}, 60); } else if (UP) {up = false; Jump_timer = SetTimeout (function () {JMP (up, top);}, 60); } else if (!up && (Robot.offsettop <)) {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 + (Run_speed) < (mousex-robot.offsetwidth)) && R Unning_dir!== ' R ') {//Make run right, if not already running_dir = ' r '; Cleartimeout (Run_timer); Run_r (1, robot.offsetleft); } else if ((MouseX < Robot.offsetleft-(run_speed)) && running_dir!== ' l ') {//make run left, if Not already running_dir = ' l '; Cleartimeout (Run_timer); run_l (1, robot.offsetleft); } } }}
Now we have completely rewritten functions and worked very well across browsers ... Unless the browser has a touch-screen input. We still need to move further so that our robots can run on whatever device. Because the touchscreen behaves somewhat differently, we need to do some extra coding on the event listener.
Touch screen Support
We need to make some new rules for the touchscreen: on the stage. When the screen is touched, the robot will run to that point until the fingertip leaves.
If the user touches the robot. The robot jumps up. In short, we need to add some additional event handlers for the previous function. And we're going to write the code this way: whenever the robotmaster function is called, it takes its own initiative.
(function () { if (stage.addeventlistener) { stage.addeventlistener (' Touchstart ', Stage_mousemove_listener, FALSE); Stage.addeventlistener (' Touchmove ', Stage_mousemove_listener, false); Stage.addeventlistener (' Touchend ', Stage_mouseout_listener, false); Stage.addeventlistener (' MouseMove ', Stage_mousemove_listener, false); Robot.addeventlistener (' mouseover ', Robot_mouseover_listener, false); Stage.addeventlistener (' mouseout ', Stage_mouseout_listener, false); } else { stage.attachevent (' onmousemove ', stage_mousemove_listener); Robot.attachevent (' onmouseover ', robot_mouseover_listener); Stage.attachevent (' onmouseout ', Stage_mouseout_listener); }) ();
We don't have to worry about the format of touch events in IE8, if there is no device that does not support touch touch. It ignores these listeners. Now, if the browser has a touch function, we need to updateStage_mousemove_listener ()function makes a difference in performance:
function Stage_mousemove_listener (e) {/* * First we check if this is a touch screens device (if it has e.touches) */IF (e.touches) {E.preventdefault ();/////We want to cancel what the browser would usually does if touched there//if the touch was WI Thin the boundaries of the stage ... if ((E.touches[0].pagex > Stageoffset.xpos) && (E.touches[0].pagex & Lt (Stageoffset.xpos + stage.offsetwidth)) && (E.touches[0].pagey > Stageoffset.ypos) && (E.touches[0].pagey < (Stageoffset.ypos + Stage.off SetHeight)) {//We set the MouseX to equal the PX location inside the stage MouseX = E.touches[0].pagex-stage Offset.xpos; } else {//If the touch is 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)) {CLE Artimeout (Run_timer); JMP (True, robot.offsettop); }} else {//finding the MouseX for Non-touch devices ...//all of our Non-touch device code here}}
You may have noticed that inRobotmakerfunction, there is no longer any "gate", however, because all of the code we invoke with the event handler isRobotmakerIn So we don't need them anymore. For our stage and characters, it is necessary to add a little bit of CSS to the touch device so that when the user fingers hold them, they do not try to cut and paste whatever picture.
#stage,. character { -webkit-user-select:none;}
At last. We declare all the robots at the bottom of the page. Use the same format. When the page loads. The event handler makes the code self-executing-this same method prevents those robot objects from becoming global variables. So, throughout the script, the only global variable we have isRobotmaker ()Function
(function () { var j = robotmaker (document.getElementById (' J '), 1, 1); var J2 = Robotmaker (document.getElementById (' J2 '),. 8, 5); var J3 = Robotmaker (document.getElementById (' J3 '), 1.1,. 5); var J4 = Robotmaker (document.getElementById (' J4 '),. 5,. 75);}) ();
See the results in glory
Summarize
I strongly recommend that you learn all the code (and all the stares). At the same time you can download four robots nationwide warranty
Happy animating!
JavaScript anime works (closing)