JavaScript动漫作品(闭幕)
笔者:Steven Riche
发布时间:2014年2一个月18
原文链接:http://code.tutsplus.com/tutorials/javascript-animation-that-works-part-4-of-4--net-35263
翻译:子毅 --------- 将JavaScript进行究竟
碎碎两句
折腾了一个多月。杂七杂八的事情加在一起。简直糟透了。
博客停了大概有一个月了,从今天起一切都是新的,做好自己就OK了
----------------------------------------------------------------------------------------------
在本系列的 p=35205">第一篇文章
介绍
在这个过程中。我们将讨论跨浏览器的代码,而且触摸屏也可用
事件处理程序
或者,当用户在‘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);
因此。在上面的几行代码中,我们说过,不管什么时候用户在舞台(stage)元素上移动鼠标。将触发一个叫做stage_mousemove_listener()的函数(注意。在命令中。我们并没有包括參数)。相似地,当用户在robot元素上移动鼠标。将触发robot_mouseover_listener(),当用户从舞台上移开鼠标,触发stage_mouseout_listenr()
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);
}
你可能会注意到那些命令的格式很相似。可是还是有一些基本的差别:一个叫做‘addEventListener',一个叫做'attachEvent',一个叫做'mousemove',然而还有一个叫做'onmousemove'。一个须要第三个參数。而另个仅仅用了两个。
混淆它们之间的不论什么一个都会导致命令不运行。这一系列的事会使你实用脑袋撞墙的冲动。不幸的是,为了是具有跨浏览器的能力,这并非我们须要额外编写的最后代码
监听函数
从编写用户在舞台上移动而触发的函数開始。
正由于它是一个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!
}
我们有个叫做e的參数在函数中,虽然我们没有传递不论什么东西给它。可是这是一个事件侦听器,我们将自己主动拥有一个叫做e的变量,这个变量存储有和事件相关的信息,比方鼠标数据。可是不同浏览器存储的方式不同,我们不得不添加额外的一个步骤。
Astik的博客
// 在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);
如今我们已经写好了mousemove侦听器,其它将会easy非常多。
对于机器人mouseover侦听器,我们仅仅须要检測机器人是否在跳跃,假设不是,停止跑动,使之跳跃。
function robot_mouseover_listener(){
if (!jump_timer || jump_timer === undefined){
clearTimeout(run_timer);
jmp(true, robot.offsetTop);
}
}
mouseout侦听器相同也非常easy。仅仅须要重置一些我们用来跟踪robot的变量,假如机器人没有跳跃,则将机器人置为站立的精灵
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);
}
})();
我们不须要操心触摸事件在IE8中的格式,假如有不论什么设备不支持触摸触摸。它将忽略这些侦听器。如今,假如浏览器具有触摸功能,我们须要更新stage_mousemove_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
}
}
你可能注意到,在RobotMaker函数里,这里不再具有不论什么”门“,可是,由于我们调用的全部具有事件处理程序的代码都在RobotMaker里。所以我们不再须要它们。对于我们的stage和characters,须要为 触摸设备加入一点特别的CSS,使得在用户手指按住它们时,它们不会尝试剪切和粘贴不论什么图片。
#stage, .character {
-webkit-user-select: none;
}
最后。我们声明全部的机器人在页面的底部。使用相同的格式。当页面载入时。事件处理器使得代码自己主动执行- 这种方法相同阻止了那些机器人对象成为全局变量。因此,在整个脚本中,我们唯一有的全局变量就是RobotMaker()函数
(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);
})();
总结
JavaScript动漫作品(闭幕)的更多相关文章
- Snabbt.js – 极简的 JavaScript 动画库
Snabbt.js 是一个简约的 JavaScript 动画库.它会平移,旋转,缩放,倾斜和调整你的元素.通过矩阵乘法运算,变换等可以任何你想要的方式进行组合.最终的结果通过 CSS3 变换矩阵设置. ...
- 10个最好的 JavaScript 动画库和开发框架
虽然 CSS3 动画功能能够让我们以简单轻松的方式实现动画效果,但是浏览器兼容性问题让人头疼.不过不用担心,我们还有另外的武器——JavaScript,它同样可以帮助你实现各种各样的动画效果,而且借助 ...
- 2019年10个最受欢迎的JavaScript动画库!
摘要: 非常炫酷的动画库! 原文:值得看看,2019 年 11 个受欢迎的 JavaScript 动画库! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 1. Three.js 超过 ...
- 2018年值得关注的10大JavaScript动画库
2018年值得关注的10大JavaScript动画库 旭日云中竹 前端早读课 1周前 前言 平时大家开发动画是采用什么方式呢?虽然18年过半,可这十个动画库是真的没听过几个,有点尴尬.今日早读文章由@ ...
- JavaScript 动画库和开发框架
1. Tween JS TweenJS 是一个简单的 JavaScript 补间动画库.能够很好的和 EaselJS 库集成,但也不依赖或特定于它.它支持渐变的数字对象属性和 CSS 样式属性.API ...
- 原生javascript封装动画库
****转载自自己发表于牛人部落专栏的文章**** 一.前言 本文记录了自己利用原生javascript构建自己的动画库的过程,在不断改进的过程中,实现以下动画效果: 针对同一个dom元素上相继发生的 ...
- 20个优秀的 JavaScript 键盘事件处理库
键盘事件是 Web 开发中最常用的事件之一,通过对键盘事件的捕获和处理可以提高网站的易用性和交互体验.下面,我们向大家介绍收集的20款优秀的 JavaScript 键盘事件处理库,帮助开发人员轻松处理 ...
- javascript运动学教程
本文系笔者学习原生javascript动效的笔记.内容基于某非著名培训机构的视频教程.并重新做了归类整理.删除了一些过时的内容.并重做了GIF图,加上了自己的一些分析. 一. 运动学基础 引子:从左到 ...
- 十大经典排序算法总结(JavaScript描述)
前言 读者自行尝试可以想看源码戳这,博主在github建了个库,读者可以Clone下来本地尝试.此博文配合源码体验更棒哦~~~ 个人博客:Damonare的个人博客 原文地址:十大经典算法总结 这世界 ...
随机推荐
- hdu 5090 Game with Pearls
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5090 题意:n个数,k,给n个数加上k的正倍数或者不加,问最后能不能凑成1 到 n的序列 题目分类:暴 ...
- WM_NCHITTEST有21种取值,常用的有HTCAPTION,HTCLIENT,HTBORDER,HTSYSMENU,HTTRANSPARENT,罗列所有VCL里对其使用的情况
我为了移动一个无标题栏的窗体,使用了WM_NCHITTEST消息,这个消息大概如下: 通常,我们拖动对话框窗口的标题栏来移动窗口,但有时候,我们想通过鼠标在客户区上拖动来移动窗口. 一个容易想到的方案 ...
- Storyboard 经常用法总结-精华版
1.prepareForSegue: Now we know what the destinationViewController is we can set its data properties. ...
- 欧舒丹 L'Occitane 活力清泉保湿面霜 - 男士护肤 - 香港草莓网StrawberryNET.com
欧舒丹 L'Occitane 活力清泉保湿面霜 - 男士护肤 - 香港草莓网StrawberryNET.com 欧舒丹 活力清泉保湿面霜 50ml/1.7oz
- ffmpeg 频中分离 video audio 截取片断
1.获取视频的信息 ffmpeg -i video.avi 2,将图片序列分解合成视频 ffmpeg -i src.mpg image%d.jpg ffmpeg -f image2 -i ...
- ADN中国团队參加微软的Kinect全国大赛获得三等奖
上周末我们团队參加了微软的Kinect全国大赛,我们的Kinect + Navisworks漫游荣膺三等奖 团队经理Joe写了篇详实的总结,我就直接转载了. http://blog.csdn.ne ...
- Android-1-电话拨号程序
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjY1MTM4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- libsvm中的dec_values以及分类结果评分问题
最近一个图像识别项目里需要对分类的结果进行打分,因为使用的是libsvm3.12,一开始决定直接将svm_predict_values函数的dec_values作为评分返回,后来研究了之后才觉得里面有 ...
- hdu4352(数位dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4352 题意:求区间L到R之间的数A满足A的的数位的最长递增序列的长度为K的数的个数. 分析:数位dp, ...
- URAL1523(dp+树状数组)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=41224#problem/B 分析:可以设dp[i][j]表示以i结尾长度为j的 ...