JavaScript动画工作原理之(完结篇)
- - CSDN博客Web前端推荐文章原作者:Steven Riche. 发布时间:2014年2月18日. 原文链接:http://code.tutsplus.com/tutorials/javascript-animation-that-works-part-4-of-4--net-35263. 翻译:子毅 --------- 将JavaScript进行到底.
原作者:Steven Riche
发布时间:2014年2月18日
原文链接:http://code.tutsplus.com/tutorials/javascript-animation-that-works-part-4-of-4--net-35263
翻译:子毅 --------- 将JavaScript进行到底
碎碎两句
折腾了一个多月,杂七杂八的事情加在一起,简直糟透了。博客停了大概有一个月了,从今天起一切都是新的,做好自己就OK了
----------------------------------------------------------------------------------------------
在本系列的 第一篇文章中,我们介绍了用精灵在web上创建简单、跨浏览器的可交互动画。在 第二篇文章中,我们让动画工作起来,而在第三篇文章中,我们整理好我们的代码,并为它在web上使用做好准备
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);
} // 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
} 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); 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);
}
}
}
} (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);
})();