笔者:Steven Riche
发布时间:2014年2一个月18
原文链接:http://code.tutsplus.com/tutorials/javascript-animation-that-works-part-4-of-4--net-35263
翻译:子毅 --------- 将JavaScript进行究竟
碎碎两句
折腾了一个多月。杂七杂八的事情加在一起。简直糟透了。
博客停了大概有一个月了,从今天起一切都是新的,做好自己就OK了
----------------------------------------------------------------------------------------------
在本系列的第一篇文章中,我们介绍了用精灵在web上创建简单、跨浏览器的可交互动画。在第二篇文章中,我们让动画工作起来,而在第三篇文章中,我们整理好我们的代码,并为它在web上使用做好准备
在这个过程中。我们将讨论跨浏览器的代码,而且触摸屏也可用
或者,当用户在‘my_other_div‘上移动鼠标时。‘my_other_function()‘运行
jQuery已经为你做好了全部的跨浏览器測试,因此,你仅仅须要输入一个命令,jQuery会在幕后翻译它使得它在每一个浏览器中都可用。此外,很多jQuery命令都比核心JavaScript更加直观、简单。
当我在舞台区域移动鼠标时。我想要全部的机器人朝着鼠标移动的方向跑。当它们抵达鼠标或者鼠标正好在它们上面,我想要它们停止移动。假如鼠标放在它们身上,我想要它们跳起来。
最后,当鼠标离开舞台,我想要它们停止跑动。我们将从绑定事件到RobotMaker函数内部開始。
stage.addEventListener(‘mousemove‘, stage_mousemove_listener, false); robot.addEventListener(‘mouseover‘, robot_mouseover_listener, false); stage.addEventListener(‘mouseout‘, stage_mouseout_listener, false);
if (stage.addEventListener){ // We will test to see if this command is available stage.addEventListener(‘mousemove‘, stage_mousemove_listener, false); robot.addEventListener(‘mouseover‘, robot_mouseover_listener, false); stage.addEventListener(‘mouseout‘, stage_mouseout_listener, false); } else { // If not, we have to use IE commands stage.attachEvent(‘onmousemove‘, stage_mousemove_listener); robot.attachEvent(‘onmouseover‘, robot_mouseover_listener); stage.attachEvent(‘onmouseout‘, stage_mouseout_listener); }
混淆它们之间的不论什么一个都会导致命令不运行。这一系列的事会使你实用脑袋撞墙的冲动。不幸的是,为了是具有跨浏览器的能力,这并非我们须要额外编写的最后代码
从编写用户在舞台上移动而触发的函数開始。
正由于它是一个mousemove侦听器,当鼠标每次在舞台区域内移动时,都将触发它(这意味着在一秒钟内将会触发多次)这个函数须要将机器人的位置和鼠标的位置作比較。并使机器人见机行事。每次函数触发,它将检測机器人须要继续朝同样的方向跑动。还是变换为其它行为。
因此,它须要像以下这样编写。
// Inside of RobotMaker // We will need to introduce a few extra variables to track var mouseX; // For tracking horizontal mouse position var running_dir = ‘‘; // For tracking if (and where) robot is currently running var 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 will be saved in ‘mouseX‘ // Then we compare ‘mouseX‘ to the robot, and decide if we need to run differently if (((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)) { // 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, then we let our current behavior continue }
不幸的是,找出mouseX有一些棘手,由于鼠标位置是还有一件不同浏览器表现不同的事。
为避免找出mouseX而进行复杂冗长的解释。正如灵感来自优秀的Quirksmode博客 (这是一个学习很多其它高级JavaScript技术的伟大源地):
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; // 我们找到了mouseX! }
// 在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);
对于机器人mouseover侦听器,我们仅仅须要检測机器人是否在跳跃,假设不是,停止跑动,使之跳跃。
function robot_mouseover_listener(){ if (!jump_timer || jump_timer === undefined){ clearTimeout(run_timer); jmp(true, robot.offsetTop); } }
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"; } } }
function run_r(phase, left){ face_right = true; running_dir = ‘r‘; if ((left + (15 * run_speed)) < (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 / 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 < 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); } } } }
假如用户触摸机器人。机器人则跳起来。总之,我们须要为之前的函数加入一些额外的事件处理器。而且我们将以这种方式来写代码:不管什么时候RobotMaster函数被调用,它都会自己主动执行。
(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); } })();
function stage_mousemove_listener(e){ /* * First we check if this is a touch screen device (if it has e.touches) */ if (e.touches){ e.preventDefault(); // we want to cancel what the browser would usually do if touched there // If the touch was within the boundaries of the stage... 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 } }
#stage, .character { -webkit-user-select: none; }
(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); })();
原文:http://www.cnblogs.com/yxwkf/p/4855357.html