• 第九节 JS运动应用


    多物体运动框架

      多个物体同时运动

        例子:多个Div,鼠标移入变宽

          单定时器,存在问题

          每个Div一个定时器

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>多个div变宽</title>
        <style>
            div{
                width: 100px;
                height: 50px;
                background: red;
                margin: 10px;
            }
            /*鼠标移入时宽度变宽;鼠标移除,恢复原状*/
        </style>
        <script>
            // window.onload = function () {
            //     var aDiv = document.getElementsByTagName('div');
            //     for (var i=0; i<aDiv.length; i++){
            //         aDiv[i].onmouseover = function(){
            //             startMove(this, 400)
            //         };
            //         aDiv[i].onmouseout = function(){
            //             startMove(this, 100)
            //         };
            //     }
            // };
            //
            // var timer = null;
            // function startMove(obj, iTarget){
            //     clearInterval(timer);
            //     timer = setInterval(function () {
            //         var speed = (iTarget - obj.offsetWidth)/6;
            //         speed = speed>0?Math.ceil(speed):Math.floor(speed);
            //         if (obj.offsetWidth==iTarget) {
            //             clearInterval(timer);
            //         } else {
            //             obj.style.width = obj.offsetWidth+speed+'px';
            //         }
            //     }, 30);
            // }
    
            //问题是,当我们把鼠标移入一个div,并快速移出,然后快速移入下一个div时,鼠标移入的第一个div有可能不能恢复原状,
            //其实问题的根源就是 整个程序就只有一个“定时器”,当第一个div在动的时候,还没有完全恢复,第二个div的定时器已经把
            // 上一个的定时器覆盖掉,所以出现这种情况,解决办法如下:
            window.onload = function () {
                var aDiv = document.getElementsByTagName('div');
                for (var i=0; i<aDiv.length; i++){
                    aDiv[i].timer = null;   //自定义属性,给每个div都加一个定时器
    
                    aDiv[i].onmouseover = function(){
                        startMove(this, 400)
                    };
                    aDiv[i].onmouseout = function(){
                        startMove(this, 100)
                    };
                }
            };
            // var timer = null;
            function startMove(obj, iTarget){
                clearInterval(obj.timer);   //关闭相应div的定时器
                obj.timer = setInterval(function () {   //开启相应div的定时器
                    var speed = (iTarget - obj.offsetWidth)/6;
                    speed = speed>0?Math.ceil(speed):Math.floor(speed);
                    if (obj.offsetWidth==iTarget) {
                        clearInterval(obj.timer);   //关闭相应div的定时器
                    } else {
                        obj.style.width = obj.offsetWidth+speed+'px';
                    }
                }, 30);
            }
        </script>
    </head>
    <body>
        <div></div>
        <div></div>
        <div></div>
    </body>
    </html>
    View Code

    多物体运动框架

      定时器作为物体的属性

      参数传递:物体、目标值

      例子:多个Div淡出淡入

        所有东西都不能共用

        属性与运动对象:速度、其他属性值(如透明度)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>多个div淡入淡出</title>
        <style>
            div{
                width: 200px;
                height: 200px;
                margin: 20px;
                float: left;
                background: red;
                filter: alpha(opacity: 30);
                opacity: 0.3;
            }
        </style>
        <script>
            window.onload=function () {
                var aDiv = document.getElementsByTagName('div');
    
                for (var i=0; i<aDiv.length;i++){
                    aDiv[i].alpha = 30;     //把每个div的alpha分开
    
                    aDiv[i].onmouseover = function () {
                        startMove(this, 100);
                    };
                    aDiv[i].onmouseout = function (){
                        startMove(this, 30);
                    };
                }
            };
            // var alpha = 30;     //虽然把alpha分开了不同的div,但是任然存在鼠标快速由一个div移入到另一个div时,透明度变化较慢的情况
            // 所以我们的解决办法是,把每个div的alpha也分开,
            function startMove(obj, iTarget) {
                clearInterval(obj.timer);
                obj.timer = setInterval(function () {
                    var speed = (iTarget-obj.alpha)/6;
                    speed = speed>0?Math.ceil(speed):Math.floor(speed);
                    
                    if (obj.alpha==iTarget) {
                        clearInterval(obj.timer);
                    } else {
                        obj.alpha+=speed;
                        obj.style.filter = 'alpha(opacity: '+obj.alpha+')';
                        obj.style.opacity = obj.alpha/100;
                    }
                }, 30);
            }
        </script>
    </head>
    <body>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
    </body>
    </html>
    View Code

    任意值的运动框架

      offset属性的Bug

        有边框的Div变宽

          用currentSty代替offset

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>a_bug_of_offset</title>
        <style>
            #div1{
                width: 200px;
                height: 200px;
                background: red;
                border: 1px solid black;
            }
            #div2{
                height: 200px;
                background: red;
                border: 1px solid black;
            }
            #div3{
                width: 200px;
                height: 200px;
                background: red;
                border: 1px solid black;
            }
        </style>
        <script>
            setInterval(function () {
                var oDiv1 = document.getElementById('div1');
    
                oDiv1.style.width = oDiv1.offsetWidth-1+'px';
                //问题来了,样式表中未加“border”之前,div确实在一直变窄,直至消失,而加入“border”之后div就开始慢慢变宽了,
                //原因是,offsetwidth获得的是div的“盒模型”(其中包括:border、padding、width等等)尺寸,究其根本原因是
                //因为width=200 左右border为2 offsetWidth=200+2=202,202-1=201px赋值给Width;
                //现在offsetWidth=201+2=203px 203-1=202px再赋值给Width;
                //offsetWidth=202+2=204px 204-1=203px再赋值给Width;如此继续,Width会越来越大,div的宽度也就越来越宽
                //
                //另外,同理,当改为:“oDiv.style.width = oDiv.offsetWidth-2+'px';”时,原先offsetWidth=200+2=202px,
                //offsetWidth-2=200px赋值给width,offsetWidth有等于200+2px,如此反复,width始终等于200px,
                //offsetWidth始终等于202px,所以当“-2”时,div不发生任何变化,
            }, 30);
    
            //解决办法是不使用offsetWidth 如下,把div2的width放到行间
            setInterval(function () {
                var oDiv2 = document.getElementById('div2');
                oDiv2.style.width = parseInt(oDiv2.style.width)-1+'px';
            }, 30);
    
            //上述解决办法,又存在一个局限性,因为“a.style.b”只能获取行间样式,而不能获取样式表中的样式,解决办法是:
            function getStyle(obj, name){   //该方法帮助我们获取非行间(样式表里的)样式
                if(obj.currentStyle){
                    return obj.currentStyle[name];
                } else {
                    return getComputedStyle(obj, false)[name];
                }
            }
            setInterval(function () {
                var oDiv3 = document.getElementById('div3');
                oDiv3.style.width = parseInt(getStyle(oDiv3, 'width'))-1+'px';
            }, 30);
        </script>
    </head>
    <body>
        <div id="div1"></div>
        <div id="div2" style=" 200px"></div>
        <div id="div3"></div>
    </body>
    </html>
    View Code

         

      原有运动框架的问题:只能让某个值运动起来,如果想让其他值运动起来,要修改程序

        由上述代码我们可以看出,offset...存在相应的bug,所以之前用过offset...的相关代码也会有同样的错误出现,开始用“offset...”仅仅是因为它比较简单,而且很容易让人们理解运动的概念,但是之后为了避免此类错误的出现,我们就不再优先考虑offset...了,所以下面改进版的“任意值的运动框架-改进版”如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>任意值变化框架-改进版</title>
        <style>
            div{
                width: 200px;
                height: 200px;
                margin: 20px;
                float: left;
                background: red;
                font-size: 14px;
                border: 1px solid blue;
            }
        </style>
        <script>
            window.onload = function () {
                var oDiv1 = document.getElementById('div1');
                oDiv1.onmouseover = function () {
                    startMove(this, 'height', 400);
                };
                oDiv1.onmouseout = function (){
                    startMove(this, 'height', 200);
                };
    
                var oDiv2 = document.getElementById('div2');
                oDiv2.onmouseover = function () {
                    startMove(this, 'width', 400);
                };
                oDiv2.onmouseout = function (){
                    startMove(this, 'width', 200);
                };
    
                var oDiv3 = document.getElementById('div3');
                oDiv3.onmouseover = function () {
                    startMove(this, 'font-size', 24);   //font-size也可以写成fontSize
                };
                oDiv3.onmouseout = function () {
                    startMove(this, 'fontSize', 14);   //font-size也可以写成fontSize
                }
    
                var oDiv4 = document.getElementById('div4');
                oDiv4.onmouseover = function () {
                    startMove(this, 'border-width', 24);    //border-width也可以写成borderWidth
                };
                oDiv4.onmouseout = function () {
                    startMove(this, 'border-width', 1);     //border-width也可以写成borderWidth
                }
            };
    
            function getStyle(obj, name){   //该方法帮助我们获取非行间(样式表里的)样式
                if(obj.currentStyle){
                    return obj.currentStyle[name];
                } else {
                    return getComputedStyle(obj, false)[name];
                }
            }
    
            function startMove(obj, attr, iTarget) {
                clearInterval(obj.timer);
                obj.timer = setInterval(function () {
                    var cur = parseInt(getStyle(obj, attr));
    
                    var speed = (iTarget-cur)/6;
                    speed = speed>0?Math.ceil(speed):Math.floor(speed);
    
                    if (cur==iTarget) {
                        clearInterval(obj.timer);
                    } else {
                        obj.style[attr] = cur+speed+'px';
                    }
                }, 30);
            }
        </script>
    </head>
    <body>
        <div id="div1">变长</div>
        <div id="div2">变宽</div>
        <div id="div3">字体变大</div>
        <div id="div4">变宽</div>
    </body>
    </html>
    View Code

    扩展的运动框架:

      运动属性作为参数

      封装opacity

        小数的问题   

      但是由于我们在上述代码中用的是:parseInt()进行取整,但是如果我们在使用透明度的时候都需要用到小数,所以此时由于parseInt()的使用,又限制了程序的完整性,解决办法如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>parseInt局限的改进</title>
        <style>
            div{
                width: 200px;
                height: 200px;
                margin: 20px;
                float: left;
                background: red;
                font-size: 14px;
                border: 10px solid blue;
                filter: alpha(opacity: 30); /*IE浏览器 物体透明度*/
                opacity: 30%;    /*Chrome、FF浏览器 物体透明度,也可以写成0.3*/
            }
        </style>
        <script>
            window.onload = function () {
                var oDiv1 = document.getElementById('div1');
                oDiv1.onmouseover = function () {
                    startMove(this, 'opacity', 100);
                };
                oDiv1.onmouseout = function (){
                    startMove(this, 'opacity', 30);
                };
            };
    
            function getStyle(obj, name){   //该方法帮助我们获取非行间(样式表里的)样式
                if(obj.currentStyle){
                    return obj.currentStyle[name];
                } else {
                    return getComputedStyle(obj, false)[name];
                }
            }
    
            function startMove(obj, attr, iTarget) {
                clearInterval(obj.timer);
                obj.timer = setInterval(function () {
                    var cur = 0;
    
                    if (attr == 'opacity') {
                        cur = Math.round(parseFloat(getStyle(obj, attr))*100);  //乘以100符合咱们平时对opacity的设置 Math.round()下面会有介绍
                    } else {
                        cur = parseInt(getStyle(obj, attr));
                    }
    
                    var speed = (iTarget-cur)/6;
                    speed = speed>0?Math.ceil(speed):Math.floor(speed);
    
                    if (cur==iTarget) {
                        clearInterval(obj.timer);
                    } else {
                        if (attr == 'opacity') {
                            obj.style.filter = 'alpha(opacity:'+(cur+speed)+')';    //IE透明度
                            obj.style.opacity = (cur+speed)/100;
    
                            var oTxt = document.getElementById('txt1');
                            oTxt.value = obj.style.opacity;
                        } else {
                            obj.style[attr] = cur+speed+'px';
                        }
    
                    }
                }, 30);
            }
    
    
            // alert(0.06*100);    //返回值为 6 没错
            // alert(0.07*100);    //返回值为:7.000000000000001,出现误差,
            // // 这是由于计算机存储容量有限,所以计算机并不一定会全部存储数据的实际值,而是近似值,但是只要是近似值就会有误差,
            // // 但是这并不会妨碍我们的使用,而且并不是PC存在这个问题,手机等计算设备都会有这种问题。
            // // 目前这种情况已经相对很少出现了,当然我们也有解决办法 Math.round() 四舍五入
            // alert(Math.round(3.499999999999999));   //返回值为3
            // alert(Math.round(3.4999999999999999));   //返回值为4
        </script>
    </head>
    <body>
        <div id="div1">变长</div>
        <input id="txt1" type="text"/>
    </body>
    </html>
    View Code

    仿Flash图片展示 - 1

      效果思路:

        两边的按钮——淡入淡出

        大图下拉——层级、高度变化

        下方的li——多物体淡入淡出

        下方的ul——位置计算

      左右按钮

        淡出淡入

          鼠标移动到按钮上,按钮会消失

            层级问题

            按钮和遮罩上都得加上事件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>仿Flash图片轮转效果</title>
        <link rel="stylesheet" type="text/css" href="31.css"/>
        <script src="31JS_StartMove.js"></script>
        <script>
            function getByClass(oParent, sClass){
                var aEle = oParent.getElementsByTagName("*");
                var aResult = [];   //存储选出来的结果
    
                for(var i=0; i<aEle.length; i++){
                    if (aEle[i].className == sClass){
                        aResult.push(aEle[i]);
                    }
                }
                return aResult;
            }
    
            window.onload = function(){
                var oDiv = document.getElementById('playimages');
                var oBtnPrev = getByClass(oDiv, 'prev')[0];
                var oBtnNext = getByClass(oDiv, 'next')[0];
                var oMarkLeft = getByClass(oDiv, 'mark_left')[0];
                var oMarkRight = getByClass(oDiv, 'mark_right')[0];
    
                var oDivSmall = getByClass(oDiv, 'small_pic')[0];
                var oUlSmall = oDivSmall.getElementsByTagName('ul')[0];
                var aLiSmall = oDivSmall.getElementsByTagName('li');
    
                var oUlBig = getByClass(oDiv, 'big_pic')[0];
                var aLiBig = oUlBig.getElementsByTagName('li');
    
                var nowZIndex = 2;    //用于改变图片的层级,层级越大,图片越靠上,最大层级的图片永远在最上方
                var now = 0;    //为上一张和下一张做准备
    
                oUlSmall.style.width = aLiSmall.length*aLiSmall[0].offsetWidth+'px';    //把放小图的div加宽,使其能放下所有图片
    
                //左右按钮
                oBtnPrev.onmouseover = oMarkLeft.onmouseover = function () {
                    startMove(oBtnPrev, 'opacity', 100);
                };
                oBtnPrev.onmouseout = oMarkLeft.onmouseout = function () {
                    startMove(oBtnPrev, 'opacity', 0);
                };
    
                oBtnNext.onmouseover = oMarkRight.onmouseover = function () {
                    startMove(oBtnNext, 'opacity', 100);
                };
                oBtnNext.onmouseout = oMarkRight.onmouseout = function () {
                    startMove(oBtnNext, 'opacity', 0);
                };
    
                //大图切换
                for (var i=0; i<aLiSmall.length; i++){
                    aLiSmall[i].index = i;
                    aLiSmall[i].onclick = function(){
                        //计算当前是哪一张照片,如果是当前显示的图片,点击小图切换是,如果点击的小图和显示的大图对应,则大图没有反应即可,避免图片重复刷新
                        if (this.index == now) return;
    
                        now = this.index;
    
                        tab();  //函数调用
                    };
    
                    aLiSmall[i].onmouseover = function () {
                        startMove(this, 'opacity', 100);
                    };
                    aLiSmall[i].onmouseout = function () {
                        if (this.index != now) {
                            startMove(this, 'opacity', 60);
                        }
                    }
                }
    
                //函数封装
                function tab(){
                    aLiBig[now].style.zIndex = nowZIndex++;
    
                    for (var i=0; i<aLiSmall.length;i++){
                        startMove(aLiSmall[i], 'opacity', 60);
                    }
                    startMove(aLiSmall[now], 'opacity', 100);
    
                    aLiBig[now].style.height = 0;
                    startMove(aLiBig[now], 'height', 320);   //控制大图片转换,转换方式是调整图片高度
    
                    if (now == 0){      //当图片是第一张图片时,第一张小图left=0,即靠左放
                        startMove(oUlSmall, 'left', 0);
                    } else if (now == aLiSmall.length-1){   //当图片为最后一张图片时,最后一张小图靠右摆放
                        startMove(oUlSmall, 'left', -(now-2)*aLiSmall[0].offsetWidth);
                    } else {    //当图片既不是第一张,也不是最后一张时,靠中间摆放
                        startMove(oUlSmall, 'left', -(now-1)*aLiSmall[0].offsetWidth);
                    }
                    // startMove(oUlSmall, 'left', -(now-1)*aLiSmall[0].offsetWidth)
                }
    
                oBtnPrev.onclick = function () {
                    now--;
                    if (now == -1){
                        now = aLiSmall.length-1;
                    }
                    tab();
                };
    
                oBtnNext.onclick = function () {
                    now++;
                    if (now == aLiSmall.length) {
                        now=0;
                    }
                    tab();  //函数调用
                };
    
                //自动播放
                var timer = setInterval(oBtnNext.onclick, 2000);
                
                oDiv.onmouseover = function () {
                    clearInterval(timer);
                };
                oDiv.onmouseout = function () {
                    timer = setInterval(oBtnNext.onclick, 2000);
                };
            };
        </script>
    </head>
    <body>
        <div id="playimages" class="play">
            <ul class="big_pic">
                <div class="prev"></div>
                <div class="next"></div>
    
                <div class="text">加载图片说明……</div>
                <div class="length">计算图片数量……</div>
    
                <a class="mark_left" href="javascript:;"></a>
                <a class="mark_right" href="javascript:;"></a>
                <div class="bg"></div>
    
                <li style="z-index: 1;"><img src="img/bg1.jpg"/></li>
                <li><img src="img/bg2.jpg"></li>
                <li><img src="img/bg3.jpg"></li>
                <li><img src="img/bg4.jpg"></li>
                <li><img src="img/bg5.jpg"></li>
                <li><img src="img/bg3.jpg"></li>
            </ul>
            <div class="small_pic">
                <ul style=" 390px;">
                    <li style="filter: alpha(opacity: 100); opacity: 1;"><img src="img/bg1.jpg"/></li>
                    <li><img src="img/bg2.jpg"></li>
                    <li><img src="img/bg3.jpg"></li>
                    <li><img src="img/bg4.jpg"></li>
                    <li><img src="img/bg5.jpg"></li>
                    <li><img src="img/bg3.jpg"></li>
                </ul>
            </div>
        </div>
    </body>
    </html>
    View Code
    body{background: #666;}
    ul{padding: 0;  margin: 0;}
    li{list-style: none;}
    img{border: 0;}
    
    .play{
        width: 400px;
        height: 430px;
        margin: 50px auto 0;
        background: #999;
        font: 12px Arial;
    }
    
    .big_pic{
        width: 400px;
        height: 320px;
        overflow: hidden;
        border-bottom: 1px solid #ccc;
        background: #222;
        position: relative;
    }
    .big_pic li{
        width: 400px;
        height: 320px;
        overflow: hidden;
        top: 0;
        left: 0;
        z-index: 0;
        background: url("img/loading.jpg") no-repeat center center;
        position: absolute;
    }
    .big_pic li img{
        width: 400px;
        height: 320px;
    }
    
    .mark_left{
        width: 200px;
        height: 320px;
        position: absolute;
        left: 0;
        top: 0;
        background: red;
        filter: alpha(opacity:0);
        opacity: 0;     /*控制左右位置,使鼠标停到左边时,左键出现*/
        z-index: 3000;
    }
    .mark_right{
        width: 200px;
        height: 320px;
        position: absolute;
        left: 200px;
        top: 0;
        background: green;
        filter: alpha(opacity:0);
        opacity: 0;
        z-index: 3000;
    }
    
    .big_pic .prev{
        width: 60px;
        height: 60px;
        background: url("img/btn.jpg") no-repeat;
        position: absolute;
        top: 130px;
        left: 10px;
        z-index: 3001;
        /*display: none;*/
        filter: alpha(opacity:0);
        opacity: 0;
        cursor: pointer;
    }
    .prev .next img{
        width: 60px;
        height: 60px;
    }
    .big_pic .next{
        width: 60px;
        height: 60px;
        background: url("img/btn.jpg") no-repeat 0 -60px;
        position: absolute;
        top: 130px;
        right: 10px;
        z-index: 3001;
        /*display: none;*/
        filter: alpha(opacity:0);
        opacity: 0;
        cursor: pointer;
    }
    
    .big_pic .text{
        position: absolute;
        left: 10px;
        top: 302px;
        z-index: 3000;
        color: #ccc;
    }
    .big_pic .length{
        position: absolute;
        right: 10px;
        bottom: 4px;
        z-index: 3000;
        color: #ccc;
    }
    .big_pic .bg{
        width: 400px;
        height: 25px;
        background: #000;
        filter: alpha(opacity=60);
        opacity: 0.6;
        position: absolute;
        z-index: 2999;
        bottom: 0;
        left: 0;
    }
    
    .small_pic{
        width: 380px;
        height: 94px;
        position: relative;
        top: 7px;
        left: 10px;
        overflow: hidden;
    }
    .small_pic ul{
        height: 94px;
        position: absolute;
        top: 0px;
        left: 0px;
    }
    .small_pic li{
        width: 120px;
        height: 94px;
        float: left;
        padding-right: 10px;
        background: url("img/loading.jpg") no-repeat center center;
        cursor: pointer;
        filter: alpha(opacity=100);
        opacity: 0.6;
    }
    .small_pic li img{
        width: 120px;
        height: 94px;
    
    }
    31.css
    function getStyle(obj, name){   //该方法帮助我们获取非行间(样式表里的)样式
        if(obj.currentStyle){
            return obj.currentStyle[name];
        } else {
            return getComputedStyle(obj, false)[name];
        }
    }
    
    function startMove(obj, attr, iTarget) {
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
            var cur = 0;
    
            if (attr == 'opacity') {
                cur = Math.round(parseFloat(getStyle(obj, attr))*100);  //乘以100符合咱们平时对opacity的设置
            } else {
                cur = parseInt(getStyle(obj, attr));
            }
    
            var speed = (iTarget-cur)/6;
            speed = speed>0?Math.ceil(speed):Math.floor(speed);
    
            if (cur==iTarget) {
                clearInterval(obj.timer);
            } else {
                if (attr == 'opacity') {
                    obj.style.filter = 'alpha(opacity:'+(cur+speed)+')';    //IE透明度
                    obj.style.opacity = (cur+speed)/100;
    
                    var oTxt = document.getElementById('txt1');
                    oTxt.value = obj.style.opacity;
                } else {
                    obj.style[attr] = cur+speed+'px';
                }
    
            }
        }, 30);
    }
    31JS_StartMove.js

    图片自行找,然后把名字改成文件中的图片名称即可,甚至不用管你找的图片尺寸,因为在CSS样式表中有对图片调整的代码。

    仿Flash图片展示 - 2

      下方li效果

        点击切换大图——选项卡

        li淡入淡出——移入移除

        ul移动——位置计算

      大图片切换

        图片层级——zIndex一直加1

        图片下拉效果(运动框架)

          可改为淡入淡出

      加入自动播放

        和选项卡一样

    重要知识点:

      多物体运动

      任意值运动

  • 相关阅读:
    windows修改环境变量的工具—Rapid Environment Editor
    JS 实现文件夹目录选择
    nginx 反向代理
    centOS7安装nginx及nginx配置
    yum安装时出现:Cannot retrieve metalink for repository: epel. Please verify its path and try again
    关于 PGP 加密与签名相关整理
    使用flink和kafka实现端到端的Exactly Once语义
    基于php的Http请求类封装
    Golang获取客户端IP
    Golang生成唯一的GUID
  • 原文地址:https://www.cnblogs.com/han-bky/p/10256204.html
Copyright © 2020-2023  润新知