JS运动从入门到精髓!哈哈

首先来看最基础的运动:单个物体向右匀速运动到某一点停止

     例子:一个按钮,一个div,点击按钮,让div向右运动到某一个位置暂停

//  原理: 1 获取物体当前的位置 oDiv.offsetleft
//        2 利用定时器,每隔一定的时间,让物体位置增加相同的距离(10px)。
//        3 判断物体是否移动到指定位置(500px),如果到达,就清除定时器

var oBtn = document.getElementById(‘btn‘);
var oDiv = document.getElementById(‘div1‘);
var iTimer = null;
oBtn.onclick = function() {
    iTimer = setInterval(function() {
        if (oDiv.offsetLeft == 500) {
            clearInterval(iTimer);
        } else {
        oDiv.style.left = oDiv.offsetLeft + 10 + ‘px‘;
        }

    }, 30);
}

//  存在问题: 1 当我们一直不停的点按钮的时候,物体运动速度会加快。
//            原因:我们每点击一次按钮,就会开启一个定时器,有时候上次定时器还没清除, 这个就开启了,当多个定时器一起物体运动就会加快。
//            解决: 在点击按钮的时候,先清除上次的定时器。保证运动中,只有一个定时器在执行。
//            2 当我们指定的位置不是500,是别的位置的时候,有可能物体停不下来。
//            原因:物体每次向前移动10px,不一定就正好到我们指定的位置,除非这个数字刚好整                    除每次移动的距离。其实也不算是个问题,但是个需要注意的点。
//            解决:在作条件判断的时候,判断范围,而不是指定的位置。(oDiv.offsetLeft >= 500) 

所以我们可以知道运动需要注意:1 运动前清除上次定时器

2 开启定时器,指向运动

3  运动中指定运动的形式(匀速缓存还是什么的),并且加入条件判断,以便停止

封装函数:对于以上运动的改进代码,我就不做具体的示范了,我们直接来进行简单的封装。在封装函数中顺便改进上面的函数了。

var oBtn = document.getElementById(‘btn‘);
var oDiv = document.getElementById(‘div1‘);
var iTimer = null;
oBtn.onclick = function() {
      startMove();
}

// 封装后的函数
function startMove() {
    clearInterval(iTimer);  //运动前清除定时器
    iTimer = setInterval(function() {
           if (oDiv.offsetLeft == 500) {
             clearInterval(iTimer);   //满足条件清除定时器
            } else {
                oDiv.style.left = oDiv.offsetLeft + 10 + ‘px‘; //每次向前移动
         }

        }, 30);
}   

扩展需求1:根据上面的函数我们可以实现,一个物体向右运动到某一个位置。那么我们现在如果有两个物体,一个向左运动,一个向右运动,且运动的目的地是不同的,那么上面的函数是不是就不满足了呢?

改进:多物体多方向运动

// 函数封装原则: 1  不变的不动
//             2  改变的东西作为参数
//             3  改变太多的进行条件判断

//  改变的是运动的物体(obj)运动方向(iSpeed)和运动的目标(iTarget) ,如下作为参数

oDiv1.onmouseover = function() {
        startMove(this,0, 10);
}
oDiv1.onmouseout = function() {
     startMove(this,-100, -10);
}

function startMove(obj, iTarget, iSpeed) {
        clearInterval(iTimer);

        iTimer = setInterval(function() {

            if (obj.offsetLeft == iTarget) {
                clearInterval(iTimer);
            } else {
                obj.style.left = obj.offsetLeft + iSpeed + ‘px‘;
            }

        }, 30);
}

扩大需求2:现在我们不仅仅改变的是物体左右移动,我们想让一个物体的透明度也能改变。能作出淡入淡出的效果。

存在的问题是

问题1 : 在css中,不同浏览器对透明度的设置方式不同。

IE:  filter: alpha(opacity=30);(0-100)
其他: opacity: 0.3;(0-1)
// 所以存在的问题是:用哪种方式来判断透明度是否到达我们所指定的目标,是用0-1,还是0-100来判断呢?

 在这里要普及一个知识 :
    alert(0.1+0.2)  //    0.30000004
    alert(0.2+0.7)  //    0.89999999

// 看上面的代码,会发现并没有像我们想象中弹出0.3,和0.9,是因为在JS中对于小数//的计算结果,是近似值。所以我们用0-100判断更加准确。

问题2 :如何获取到物体的透明度,用obj.style.opacity 吗?

这里要说明一个知识点,在JS中用style只能获取行间样式。 不能获取css中的样式。这个时候我们用什么呢?下面的两个方法可以获取非行间样式,有兼容问题:

1  getComputedStyle: getComputedStyle(element,随意值(写什么都可以,比如false)).attr:这个获取的是计算机计算后的样式,不能获取复合样式,只有标准浏览器支持IE6 7 8不兼容。

2  currentStyle :currentStyle[attr],只有IE6 7 8兼容 ,可以获取非行间样式,还可以获取自定义样式。

所以需要做一下兼容,我们可以封装成一个函数,如下:

function getStyle ( obj, attr ) {

    if(obj.currentStyle){
            obj.currentStyle[attr]
     }else{
          getComputedStyle( obj )[attr];
     }

}

//简写方式
function getStyle ( obj, attr ) {

     return obj.currentStyle?obj.currentStyle[attr] : getComputedStyle( obj )[attr];

}

//注意 IE下虽然没有opacity,但也能获取到opacity值,主要是因为currentStyle的原因,它能读取到任何样式的值,哪怕不存在

所以对于透明度的改变,我们可以封装成如下的函数:

function startMove2(obj, iTarget, iSpeed) {
   clearInterval(iTimer);
   var iCur = 0;       //用来存放当前的透明度值
   iTimer = setInterval(function() {
       // iCur = getStyle( obj, ‘opacity‘ ) * 100; // 因为getStyle取出来的是小数,乘以100,        是29.999900000045 这样的数,这样我们无法和iTarget进行判断,所以我们可以进行四舍五入,如下:
       iCur = Math.round(getStyle( obj, ‘opacity‘ ) * 100);
       if (iCur == iTarget) {
          clearInterval(iTimer);
       } else { //对不同的浏览器进行分别处理
           obj.style.opacity = (iCur + iSpeed) / 100;
           obj.style.filter = ‘alpha(opacity=‘+ (iCur + iSpeed) +‘)‘;
      }
    }, 30);
}

这只是改变透明度的函数封装,要是能把透明度的封装函数和前面的运动封装函数,结合起来,不就能封装成一个可以改变透明度,也可以改变位置的函数了吗。。。。

那么依照我们的合并原则,找出两个封装函数的不同之处:

运动的属性不同(attr)

2 因为不同的属性处理不同,其实主要是透明度处理是有差别的,其他宽高改变位置改变其实都一样)这个时候的差别,可以采用判断来解决

// 还解决了解决了一个问题是因为之前只有一个定时器,现在因为有多个属性可以运动了,所以就不能只用一个定时器了去控制了,每个物体运动的时候就应该有自己的定时器,所以就把定时器就用obj.timer上,这样每个物体都不同啦。

 function startMove(obj, attr, iTarget, iSpeed) {
        clearInterval(obj.iTimer);
        var iCur = 0;

        obj.iTimer = setInterval(function() {
            //对透明度进行判断如果是就进行上面的处理,不是就进行下面的处理
            if (attr == ‘opacity‘) {
                iCur = Math.round(getStyle( obj, ‘opacity‘ ) * 100);
            } else {
                iCur = parseInt(getStyle(obj, attr));
            }

            if (iCur == iTarget) {
                clearInterval(obj.iTimer);
            } else {
                if (attr == ‘opacity‘) {
                    obj.style.opacity = (iCur + iSpeed) / 100;
                    obj.style.filter = ‘alpha(opacity=‘+ (iCur + iSpeed) +‘)‘;
                } else {
                    obj.style[attr] = iCur + iSpeed + ‘px‘;
                }
            }

        }, 30);
    }

    function getStyle(obj, attr) {
        if (obj.currentStyle) {
            return obj.currentStyle[attr];
        } else {
            return getComputedStyle(obj, false)[attr];
        }
    }

不过上面的函数,还是不能满足某些需求,比如我想要一个物体的两个属性同时运动,下面这样是实现不了的。

//下面的运动会清除掉上面的定时器

startMove(this, ‘width‘, 200, 10);
startMove(this, ‘height‘, 200, 10);

那么怎么样实现这两个属性可以同时运动呢?这个时候我们可以考虑用json的格式

oDiv1.onclick = function() {
        startMove(this, {
            width : 200,
            height: 300
        }, 10);
}
 function startMove(obj, json, iSpeed) {
        clearInterval(obj.iTimer);
        var iCur = 0;

        obj.iTimer = setInterval(function() {
            //定时器每走一下就要把要运动的属性都推进一次

             for ( var attr in json ) {

                 var iTarget = json[attr];//把我们传进来的属性值赋给目标值

                  if (attr == ‘opacity‘) {
                    iCur = Math.round(getStyle( obj, ‘opacity‘ ) * 100);
                  } else {
                    iCur = parseInt(getStyle(obj, attr));
                  }

                  if (iCur == iTarget) {
                    clearInterval(obj.iTimer);
                   } else {
                        if (attr == ‘opacity‘) {
                            obj.style.opacity = (iCur + iSpeed) / 100;
                             obj.style.filter = ‘alpha(opacity=‘+ (iCur + iSpeed) +‘)‘;
                         } else {
                           obj.style[attr] = iCur + iSpeed + ‘px‘;
                         }
                    }

             }

        }, 30);
    }

    function getStyle(obj, attr) {
        if (obj.currentStyle) {
            return obj.currentStyle[attr];
        } else {
            return getComputedStyle(obj, false)[attr];
        }
    }

存在问题:上面的运动速度都是一样的,但是传进去的目标点是不一样的,这个时候就会有一个属性先到,那么运动就终止了。所以我们需要解决的是,当所有的属性都到达了目标点,才让运动终止。

解决:定义一个开关,每次运动前假设它是真的,在运动中,只要有一个属性没运动到终点,就把开关变成假,在循环外面进行判断,当所有属性都运动到终点了,开关肯定都是真的,就会清除定时器了。

oDiv1.onclick = function() {
        startMove(this, {
            width : 200,
            height: 300
        }, 10);
}
 function startMove(obj, json, iSpeed) {
        clearInterval(obj.iTimer);
        var iCur = 0;

        obj.iTimer = setInterval(function() {
            //定时器每走一下就要把要运动的属性都推进一次
            var iBtn = true;//每一次运动前都初始化为真,就是假设所有属性都到了

             for ( var attr in json ) {

                 var iTarget = json[attr];//把我们传进来的属性值赋给目标值

                  if (attr == ‘opacity‘) {
                    iCur = Math.round(getStyle( obj, ‘opacity‘ ) * 100);
                  } else {
                    iCur = parseInt(getStyle(obj, attr));
                  }

                  if (iCur != iTarget) {
                        iBtn = false; //如果有一个属性没到,就把这个开关变成假if (attr == ‘opacity‘) {
                            obj.style.opacity = (iCur + iSpeed) / 100;
                             obj.style.filter = ‘alpha(opacity=‘+ (iCur + iSpeed) +‘)‘;
                         } else {
                           obj.style[attr] = iCur + iSpeed + ‘px‘;
                         }
                    }

             }
  //在这里来看下,所有属性是不是都到了目标点,当这里变真的了,说明所有属性都到了目标点,就可以清除定时器了
            if (iBtn) {
                clearInterval(obj.iTimer);
            }

        }, 30);
    }

    function getStyle(obj, attr) {
        if (obj.currentStyle) {
            return obj.currentStyle[attr];
        } else {
            return getComputedStyle(obj, false)[attr];
        }
    }

扩大需求:假如我们这次实现的不是多个属性同时运动,我希望先把高改变,接着再改变宽,这个时候,我们需要的就是个回调函数了(fn)。za

oDiv1.onclick = function() {

        startMove(this, {
            width : 200
        }, 10, function() {
            startMove(this, {
                height : 200
            }, 10);
        });
    }

    function startMove(obj, json, iSpeed, fn) {
        clearInterval(obj.iTimer);
        var iCur = 0;

        obj.iTimer = setInterval(function() {

            var iBtn = true;

            for ( var attr in json ) {

                var iTarget = json[attr];

                if (attr == ‘opacity‘) {
                    iCur = Math.round(getStyle( obj, ‘opacity‘ ) * 100);
                } else {
                    iCur = parseInt(getStyle(obj, attr));
                }

                if (iCur != iTarget) {
                    iBtn = false;
                    if (attr == ‘opacity‘) {
                        obj.style.opacity = (iCur + iSpeed) / 100;
                        obj.style.filter = ‘alpha(opacity=‘+ (iCur + iSpeed) +‘)‘;
                    } else {
                        obj.style[attr] = iCur + iSpeed + ‘px‘;
                    }
                }

            }

            if (iBtn) {
                clearInterval(obj.iTimer);
                fn && fn.call(obj);  //如果回调函数存在再执行,call方向为了修正this的指向,之前关于this文章有讲过这个用法。
            }

        }, 30);
    }

    function getStyle(obj, attr) {
        if (obj.currentStyle) {
            return obj.currentStyle[attr];
        } else {
            return getComputedStyle(obj, false)[attr];
        }
    }
时间: 2024-10-12 07:12:52

JS运动从入门到精髓!哈哈的相关文章

JS运动从入门到兴奋1

hello,我是沐晴,一个充满了才华,却靠了照骗走江湖的前端妹子.在这个充满PS的年代,这你们都信,哈哈,废话不多说,今天要分享的是关注JS运动的知识.楼主一直认为,不管学习什么,核心思想才是王道,掌握了思想,不管需求怎么改变,我们都能把它玩弄于股掌之中...下面我们就由浅入深走进运动的世界吧. 首先来看最基础的运动:单个物体向右匀速运动到某一点停止      例子:一个按钮,一个div,点击按钮,让div向右运动到某一个位置暂停 // 原理: 1 获取物体当前的位置 oDiv.offsetle

JS运动1 (转)

JS运动从入门到兴奋1 http://www.cnblogs.com/moqing/p/5666476.html hello,我是沐晴,一个充满了才华,却靠了照骗走江湖的前端妹子.在这个充满PS的年代,这你们都信,哈哈,废话不多说,今天要分享的是关注JS运动 的知识.楼主一直认为,不管学习什么,核心思想才是王道,掌握了思想,不管需求怎么改变,我们都能把它玩弄于股掌之中...下面我们就进入运动的世界吧. 首先来看最基础的运动:单个物体向右匀速运动到某一点停止      例子:一个按钮,一个div,

Html5之高级-7 HTML5 Chart.js(概述、入门、使用)

一.Chart.js 概述 Chart.js 简介 - Chart.js 是一个简单.面向对象.为设计者和开发者准备的图表绘制工具库 - 官方地址: http://www.chartjs.org/ Chart.js 特点 - 基于 HTML 5 - Chart.js 基于 HTML5 canvas技术,支持所有现代浏览器,并且针对IE7/8提供了降级替代方案 - 简单.灵活 - Chart.js 不依赖任何外部工具库,轻量级(压缩之后仅有4.5k),并且提供了加载外部参数的方法 Chart.js

基于Aforge的物体运动识别-入门

基于Aforge的物体运动识别-入门篇chatbot人工智能机器人开发,提供教学视频>>>   0 收藏(2) 本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 最近看到越来越多人在做物体运动识别(例如:"第六感"中的指套),而且我最近也有点闲空,所以也来玩玩.....大多数人都是用Opencv来做,那我就不做重复的工作了,换个别的开源类库~~~Aforge. 来自百度知道的Aforge介绍:AForge.NET 是一个专门为开

带无缝滚动的轮播图(含JS运动框架)

今天学习了一下轮播图的写作,想到前一阵学过的无缝滚动得思想,所以就把轮播与滚动结合了一下.不过我的代码的神逻辑我自己都不敢恭维,在没网没参照的情况下,只能硬着头皮往下写,希望跟大家共勉吧. js运动框架的代码如下: 1 //获取样式 2 function getStyle(obj,attr){ 3 if(obj.currentStyle){ 4 return obj.currentStyle[attr]; 5 }else{ 6 return getComputedStyle(obj,false)

关于js运动的一些总结

js运动实现,有两种.一种是速度版,另一种是时间版. 速度版是通过对速度的加减乘除,得出元素的运动数据.时间版是通过对时间进行Tween公式运算,得出元素的运动数据. 速度版运动优点:容易在运动过程中,对运动做一些修改. 时间版运动优点:切换或缩小浏览器页面,浏览器会对网页定时器进行停缓处理.这样会导致一些速度版运动bug.因为时间版运动是通过记录时间变化区间,来对运动进行控制.所以不会有这种bug. 运动形式有:缓冲运动,碰撞运动,重力运动.缓冲运动,是速度自身也在变化的结果.碰撞运动,是碰撞

简单的JS运动封装实例---侧栏分享到

1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 5 <title>无标题文档</title> 6 <style> 7 #div1 {width: 100px; height: 200px; background: red;

Html5之高级-9 HTML5 Two.js(概述、入门)

一.Two.js 概述 Two.js 简介 - Two.js 是一个面向现代 Web 浏览器提供绘制二维图形的 API ,它允许使用不同的上下文,而使用相同的 API 进行绘制 - Two.js 所支持的上下文: - SVG - Canvas - WebGL - 官方地址: http://jonobr1.github.io/two.js/ Two.js 特点 - 专注于矢量图: - Two.js 是深度实现具有动画效果的矢量图 - Two.js 致力于更简洁地创建矢量图及动画效果 - Two.j

js运动-完美运动框架

在上一篇的<js运动-同时运动>中说过,我们的运动框架还存在一个问题,那究竟是什么问题那?把上一篇的程序做一下调整 oDiv.onmouseover = function () { //startMove(oDiv,{width:300,height:300,opacity:30}); startMove(oDiv,{width:204,height:300,opacity:30}); } 在鼠标移入的时候,我们让width不变成300,而是变成204,看看会有什么变化那?? 从图可以看出,当