Javascript使用三大家族和事件来DIY动画效果相关笔记(五)

1.client家族

◆box.clientWidth:表示盒子的宽度加padding

◆box.clientHeight:表示盒子的高度加padding

◆box.clientTop:表示盒子上边的border大小

◆box.clientLeft:表示盒子左边的border大小

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>client家族</title>
    <style type="text/css">
        #box {
            width: 200px;
            height: 200px;
            border: 5px solid #000;
        }
    </style>
</head>
<body>
<div id="box"></div>
<script>
    console.log(box.clientWidth);//表示盒子的宽度加padding
    console.log(box.clientHeight);//表示盒子的高n度加padding
    console.log(box.clientTop);//表示盒子上边的border大小
    console.log(box.clientLeft);//表示盒子左边的border大小
</script>
</body>
</html>


2.offset与scroll和client他们的width、height的区别

◆offsetWidth和offsetHeight代表着盒子的宽高(如果盒子定义的了宽高,就以定义的宽高为主,如果盒子没有定义宽高就以盒子内容为主)加上padding+border。
◆scrollWidth和scrollHeight代表着盒子的内容的宽高(如果内容的宽高小于盒子定义的宽高,那么就以盒子定义的宽高为主,如果盒子的内容宽高大于盒子定义一个宽高,那么久以盒子的内容的宽高为主)+padding。

◆clientWidth和clientHeight代表着盒子的宽高(就算内容超过盒子,它也只获取盒子定义的宽高,如果盒子没有定义宽高,那么就获取内容的宽高)+padding。


3.offset与scroll和client他们的top、left的区别

◆offsetTop和offsetLeft代表着距离最近的父系盒子带有定位的盒子之间的距离,也就是带有定位的盒子与盒子之间的上边的距离和左边的距离,如果父系盒子中没有定位的盒子,那么就取当前盒子距离浏览器(0,0)坐标点的距离。
◆scrollTop和scrollLeft代表着被卷去的距离,除了document之外其它盒子也能用,但是盒子必须要有滚动条,但是自己模拟的滚动条不行,只能使用css样式overflow:scroll;弄出来的滚动条才行。

◆clientTop和clientLeft代表着clientWidth和clientHeight不包括的上border和左border,而且只能够获取到上边的border和左边的border。


4. 使用client对象检测浏览器的宽度和高度(可视区域),也就是当你放大缩小时宽度高度就会发生变化,因为可视区域也发生了变化,检测的方式与获取scollLeft和scrollTop类似

◆无论有没有DTD,在IE9及其以上的版本的浏览器和一些主流浏览器可以使用

window.innerWidth和window.innerHeight

来检测并获取当前浏览器可视区域的宽高,在IE9以下时,获取的值都是undefined。

◆当有DTD时,可以使用

document.documentElement.clientWidth和document.documentElement.clientHeight

来检测并获取当前任何版本浏览器可视区域的宽高,如果没有DTD时用这个只能够正常检测IE任何版本的浏览器的可视区域的宽高。

◆当没有DTD时,可以使用

document.body.clientWidth和document.body.clientHeight

在IE9以上的浏览器及各个主流浏览器检测当前浏览器的可视区域的宽高,但是有DTD时无法正常检测任何版本的浏览器的可视区域的宽高。

★所以兼容性写法和scrollTop与scrollLeft有点不一样

 return {
            width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
            height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
        }
,不能够正常检测的是指高度,高度无法正常检测,宽度时而能够正常检测时而不能够正常检测,所以这种兼容性写法,可能在一些老的浏览器中还是会出现问题,但是这个已经是最好的兼容性写法了。◆使用client检测浏览器可视区域宽高:
<!--<!DOCTYPE html>-->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用client检测浏览器可视区域宽高</title>
</head>
<body>
<script>

    /**
     * 使用client对象检测浏览器的宽度和高度(可视区域),
     * 也就是当你放大缩小时宽度高度就会发生变化,
     * 因为可视区域也发生了变化,
     * 检测的方式与获取scollLeft和scrollTop类似
     * ◆无论有没有DTD,
     * 在IE9及其以上的版本的浏览器和一些主流浏览器
     * 可以使用window.innerWidth和window.innerHeight来检测
     * 并获取当前浏览器可视区域的宽高,
     * 在IE9以下时,获取的值都是undefined。
     * ◆当有DTD时,可以使用document.documentElement.clientWidth
     * 和document.documentElement.clientHeight来检测
     * 并获取当前任何版本浏览器可视区域的宽高,
     * 如果没有DTD时用这个只能够正常检测IE任何版本的浏览器的可视区域的宽高。
     * ◆当没有DTD时,可以使用document.body.clientWidth和
     * document.body.clientHeight在IE9以上的浏览器及各个主流浏览器检测
     * 当前浏览器的可视区域的宽高,
     * 但是有DTD时无法正常检测任何版本的浏览器的可视区域的宽高。
     * ★所以兼容性写法和scrollTop与scrollLeft有点不一样【
     return {
            width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
            height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
        }
     】,
     *不能够正常检测的是指高度,高度无法正常检测,
     * 宽度时而能够正常检测时而不能够正常检测,
     * 所以这种兼容性写法,可能在一些老的浏览器中还是会出现问题,
     * 但是这个已经是最好的兼容性写法。
     */
        //浏览器可视区域大小改变事件(只要浏览器可视区域有1像素的改变都会触发这个事件)
    window.onresize = fn;

    function fn() {
        console.log(window.innerWidth + " " + window.innerHeight);
        console.log(document.documentElement.clientWidth + " " + document.documentElement.clientHeight);
        console.log(document.body.clientWidth + " " + document.body.clientHeight);
        document.title = client().width + "px  " + client().height + "px";
    }

    fn();//首次打开浏览器,并不一定会触发window.onresize事件,所以先执行一次
    /**
     * 功能:用来检测浏览器可视区域的兼容性的client对象
     * @returns {{width: (Number|number), height: (Number|number)}}
     */
    function client() {

        return {
            width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
            height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
        }
    }

</script>
</body>
</html>


5.页面适配浏览器:根据浏览器可视宽度给页面上颜色

◆window.onresize事件是可视区域大小改变事件,只要浏览器可视区域发生1px的变化,都会触发window.onresize事件,就像window.onscroll事件一样,只要滚动条中的滑块儿移动1px,都会触发window.onscroll事件,注意:首次打开浏览器并不一定会触发window.onresize事件,只有当你改变浏览器窗体大小的时候才会触发。

◆根据浏览器可视宽度给页面上颜色:在css3没有退出媒体查询之前就是使用这种方式,来让网页来根据浏览器的可视区域动态适配css样式的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>根据浏览器可视宽度给页面上颜色</title>
</head>
<body>
<script>
    //需求:当屏幕宽度大于960时就给页面红色背景,
    // 当屏幕宽度小于等于960大于640时就给页面上蓝色,
    // 当屏幕宽度小于等于640时就给页面上绿色


    //浏览器可视区域的大小改变的事件
    window.onresize = fn;
    function fn() {
        if (client().width > 960) {
            document.body.style.backgroundColor = "#f00";
        } else if (client().width > 640) {
            document.body.style.backgroundColor = "#00f";
        } else {
            document.body.style.backgroundColor = "#0f0";
        }
        document.title = client().width + "px  " + client().height + "px";
    }

    fn();

    function client() {
        return {
            width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
            height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
        }
    }

</script>
</body>
</html>


6.获取屏幕分辨率的高度和宽度可以window.screen.width和window.screen.height来获取

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用screen对象检测屏幕分辨率大小</title>
</head>
<body>
<script>
    window.onresize=fn();
    function fn(){
        document.title=window.screen.width+"px   "+window.screen.height+"px";
    }
    fn();
</script>
</body>
</html>


7.事件冒泡

◆简单描述:事件冒泡:当一个元素上的事件被触发的时候,其所有父系容器如果定义了和这个元素被触发的事件时,那就会触发其所有父系容器的这个事件,比如鼠标点击了一个按钮,按钮设置了单击事件,按钮的父容器也设置了单击事件,那么你点击鼠标按钮时触发了单击事件,于此同时也会触发父容器的单击事件,元素开始不断的往上冒泡,一直冒泡到dom树的顶端

◆冒泡的原理:因为子容器在父容器中,你点击子容器的时候,其实也相当于点击了父容器的区域,所以就等于你先点击了子容器,然后你由点击了父容器的区域,于是乎当你给子容器和父容器都设置了单击事件时,先触发子容器的单击事件然后再触发父容器的单击事件,如果父容器的父容器也还设置了单击事件,那么就会一直往上触发单击事件。

◆事件传播阶段分三个:捕获阶段、冒泡阶段、目标阶段
    ◇事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)为止。
    ◇事件冒泡阶段:事件从事件目标(target)开始往上冒泡直到页面的最上一级标签。
    ☆使用捕获的方式执行事件可是使用对象.addListenerEvent("事件",fn,true);来实现,使用冒泡的方式执行事件可以使用对象.on事件=fn;来实现。
    ◇事件目标阶段:其实很像是在捕获阶段是从外往内的,将每一个事件push进一个数组中,冒泡阶段是从数组中pop出来,事件目标阶段,将pop出的事件的方法执行,整个过程很像是一个进栈出栈然后执行。

◆冒泡顺序:

    ◇IE6.0:div->body->html->document

    ◇其它浏览器:div->body->html->document->window

    ☆这些事件不会冒泡也不能冒泡:blur、focus、load、unload、onmouseenter、onmouseleave

◆判断一个事件默认冒不冒泡,使用event.bubbles,如果返回值为true则这个事件冒泡,反之这个事件不冒泡。在冒泡中找到最开始的第一个触发这个事件的对象,使用event.target,谁是第一个泡泡,target就指向谁,但是在IE678中使用了srcElement,所以就需要兼容性的写法,有两种,一种直接用 || 一种是用三元运算符

var obj=event.target||event.srcElement;//返回true就是冒泡
var obj=event.target?event.target:event.srcElement;//返回true就是冒泡
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡的相关信息</title>
    <style type="text/css">

        #box1 {
            width: 500px;
            height: 500px;
            background-color: #f0f;
        }

        #box2 {
            width: 400px;
            height: 400px;
            background-color: #0ff;
        }

        #box3 {
            width: 300px;
            height: 300px;
            background-color: #ff0;
        }

        #box4 {
            width: 200px;
            height: 200px;
            background-color: #f00;
        }

    </style>
</head>
<body>
<div id="box1">
    <div id="box2">
        <div id="box3">
            <div id="box4"></div>
        </div>
    </div>
</div>

<script>
    /**
     * 1.事件冒泡:
     * 当一个元素上的事件被触发的时候,
     * 其所有父系容器如果定义了和这个元素被触发的事件时,
     * 那就会触发其所有父系容器的这个事件,
     * 比如鼠标点击了一个按钮,
     * 按钮设置了单击事件,
     * 按钮的父容器也设置了单击事件,
     * 那么你点击鼠标按钮时触发了单击事件,
     * 于此同时也会触发父容器的单击事件,
     * 元素开始不断的往上冒泡,
     * 一直冒泡到dom树的顶端,
     *
     * 2.冒泡的原理:
     * 因为子容器在父容器中,
     * 你点击子容器的时候,
     * 其实也相当于点击了父容器的区域,
     * 所以就等于你先点击了子容器,
     * 然后你由点击了父容器的区域,
     * 于是乎当你给子容器和父容器都设置了单击事件时,
     * 先触发子容器的单击事件然后再触发父容器的单击事件,
     * 如果父容器的父容器也还设置了单击事件,
     * 那么就会一直往上触发单击事件。
     *
     * 3.事件传播阶段分三个:
     * 捕获阶段、冒泡阶段、目标阶段
     *
     * 事件捕获阶段:
     * 事件从最上一级标签开始往下查找,
     * 知道捕获到事件目标(target)为止。
     *
     * 事件冒泡阶段:
     * 事件从事件目标(target)开始往上冒泡直到页面的最上一级标签。
     * 使用捕获的方式执行事件可是使用对象.addListenerEvent("事件",fn,true);来实现,
     * 使用冒泡的方式执行事件可以使用对象.on事件=fn;来实现。
     *
     *
     * 4.冒泡顺序:
     * IE6.0:div->body->html->document
     * 其它浏览器:div->body->html->document->window
     * 这些事件不会冒泡也不能冒泡:
     * blur、focus、load、unload、onmouseenter、onmouseleave
     */



        //事件冒泡  这种方式 事件是以冒泡的方式执行的  由内到外
    box1.onclick = fn;
    box2.onclick = fn;
    box3.onclick = fn;
    box4.onclick = fn;
    document.body.onclick = fn;

    //事件捕获的方式执行   由外到内
    //    box1.addEventListener("click", function(){
    //        alert("box1");
    //    },true);
    //    box2.addEventListener("click", function(){
    //        alert("box2");
    //    },true);
    //    box3.addEventListener("click", function(){
    //        alert("box3");
    //    },true);
    //    box4.addEventListener("click", function(){
    //        alert("box4");
    //    },true);
    //    document.body.addEventListener("click", function(){
    //        alert("document");
    //    },true);

    function fn() {
        alert((this.getAttributeNode("id") ? this.getAttributeNode("id").nodeValue : "document"));
    }
</script>

</body>
</html>


8.取消事件冒泡

◆取消事件冒泡的方式,在IE678里面使用 event.cancelBubble=ture;表示取消冒泡,但是在IE9及其以上的主流浏览器使用的是event.stopPropagation();表示停止传播,也就是停止向外冒泡,阻止冒泡的兼容性写法

obj.onmouseover=function(event){
     //获取兼容性的事件对象
    event=event||window.event;
   if(event&&event.stopPropagation){
	event.stopPropagation();//停止冒泡
    }else{
   	event.cancelBubble=true;//取消冒泡
    }	
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>取消事件冒泡</title>
    <style type="text/css">

        #box1 {
            width: 500px;
            height: 500px;
            background-color: #f0f;
        }

        #box2 {
            width: 400px;
            height: 400px;
            background-color: #0ff;
        }

        #box3 {
            width: 300px;
            height: 300px;
            background-color: #ff0;
        }

        #box4 {
            width: 200px;
            height: 200px;
            background-color: #f00;
        }

    </style>
</head>
<body>
<div id="box1">
    <div id="box2">
        <div id="box3">
            <div id="box4"></div>
        </div>
    </div>
</div>
<script>
    /**
     * 取消事件冒泡的方式,
     * 在IE678里面使用event.cancelBubble=ture;表示取消冒泡,
     * 但是在IE9及其以上的主流浏览器使用的是
     * event.stopPropagation();
     * 表示停止传播,
     * 也就是停止向外冒泡,
     */

    //需求:阻止box1和box4的事件冒泡
    //思路:在IE678 里使用事件对象的 event.cancelBubble = true;//取消冒泡
    //      在其它浏览器里使用事件对象的 event.stopPropagation();//停止传播
    //步骤:
    //1.获取事件源及相关元素对象
    //2.绑定事件源
    //3.书写事件驱动程序

    box1.onclick = function (event) {
        //获取兼容性的事件对象
        event = event || window.event;
        //判断是否不是IE678
        if (event && event.stopPropagation) {
            event.stopPropagation();//停止传播
        } else {
            event.cancelBubble = true;//取消冒泡
        }

        alert("box1这里开始停止冒泡");

    }

    box2.onclick = function (event) {
        //获取兼容性的事件对象
        event = event || window.event;
        alert("box2冒泡吗?答案是:" + event.bubbles);
    }

    box3.onclick = function (event) {
        //获取兼容性的事件对象
        event = event || window.event;
        alert("box3冒泡吗?答案是:" + event.bubbles);

    }

    box4.onclick = function () {
        //获取兼容性的事件对象
        event = event || window.event;
        //判断是否不是IE678
        if (event && event.stopPropagation) {
            event.stopPropagation();//停止传播
        } else {
            event.cancelBubble = true;//取消冒泡
        }

        alert("box4一开始就停止冒泡");
    }
    document.body.onclick = function () {
        alert("document");
    }

</script>
</body>
</html>


9.事件冒泡灵活运用之事件委托

◆利用事件冒泡和event.target可以减少很多不必要的事件的定义,通过判断事件源的第一个对象,就知道是谁最开始触发了这个事件,那么就可以在最大的那个父容器的事件里面做最直接的事情了,页面元素的事件其实一直都存在,只不过是内部的事件驱动程序没有写罢了,所以就算你没有给页面元素手动设置事件,也能够通过event.target来找到触发事件的第一个事件源对象,

使用事件冒泡和事件源来显示隐藏模态框:模态框效果,这个很常用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>利用事件冒泡和事件源来显示隐藏模态框</title>
    <style type="text/css">
        html, body {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        .mask {
            height: 100%;
            width: 100%;
            background-color: rgba(0, 0, 0, 0.6);
            overflow: hidden;
            display: none;
            position: fixed;
            left: 0;
            top: 0;
        }

        .login {
            width: 450px;
            height: 380px;
            background-color: #ffc;
            margin: 200px auto;
            cursor: pointer;

        }

    </style>
</head>
<body>
<a href="#">登陆</a>
<a href="#">注册</a>
<div class="mask">
    <div class="login" id="login"></div>
</div>
<script>
    //需求:当点击登陆链接时,弹出模态框,
    // 模态框弹出之后,点击登陆部分之外的部分就隐藏模态框
    //思路:设置登陆链接点击事件,然后设置文档对象的点击事件
    //      点击登陆连接之后,显示模态框,由于事件冒泡,
    //      所以也会触发文档对象的单击事件,
    //      判断第一个事件源是不是login,
    //      如果是login就不隐藏,反之就隐藏,
    //      但是登陆链接的点击事件要取消冒泡,
    //      不然就会导致点击登陆链接之后也会隐藏模态框
    //步骤:
    //1.获取事件源及相关元素对象
    //2.绑定事件
    //3.书写事件驱动程序

    //1.获取事件源及相关元素对象
    var a = document.getElementsByTagName("a")[0];
    var mask = document.getElementsByTagName("div")[0];
    //2.绑定事件
    a.onclick = function (event) {
        //3.书写事件驱动程序

        //获取兼容性的事件对象
        event = event || window.event;
        //取消默认的冒泡
        if(event&&event.stopPropagation){
            event.stopPropagation();//停止传播  停止冒泡
        }else {
            event.cancelBubble=true;//取消冒泡 兼容IE678
        }
        show(mask);

    }

    /**
     * 利用事件冒泡和event.target可以减少很多不必要的事件的定义,
     * 通过判断事件源的第一个对象,
     * 就知道是谁最开始触发了这个事件,
     * 那么就可以在最大的那个父容器的事件里面做最直接的事情了,
     * 页面元素的事件其实一直都存在,
     * 只不过是内部的事件驱动程序没有写罢了,
     * 所以就算你没有给页面元素设置事件,
     * 也能够通过event.target来找到触发事件的第一个事件源对象。
     */

    document.body.onclick = function (event) {
        //3.书写事件驱动程序

        //获取兼容性的事件对象
        event = event || window.event;

        //获取兼容性的第一个事件源对象
        var obj = event.target || event.srcElement;

        //判断这个对象是否不是login对象
        if (obj.id !== "login") {  //通过这种方式 减少了很多事件的定义
            hide(mask);
        }
        console.log(obj);


    }

    function show(element) {
        element.style.display = "block";
    }
    function hide(element) {
        element.style.display = "none";
    }


</script>
</body>
</html>

◆js中的【事件委托】是通过事件冒泡来实现的,通过设置父容器的事件,当调用自己的事件时,在父容器那里去执行,从而,当子容器过多时减少了事件过多的定义,只需要定义一个父容器的事件即可,但是在父容器的事件中需要过滤,因为并不是所有的子元素都需要定义事件,所以可能需要在父容器中设置判断,判断当前触发的第一个事件源对象是否符合要求,如果符合的话就执行。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>通过事件冒泡来进行事件委托</title>
    <style type="text/css">
        li {
            height: 30px;
            line-height: 30px;
            background-color: #f00;
            margin-bottom: 10px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<button>来1个移民Li</button>
<ul>
    <li>我是土著li</li>
    <li>我是土著li</li>
    <li>我是土著li</li>
    <li>我是土著li</li>
    <li>我是土著li</li>
</ul>
<script>
    var button = document.getElementsByTagName("button")[0];
    var ul = document.getElementsByTagName("ul")[0];

    //来五个移民li
    button.onclick = function () {
        var li = document.createElement("li");
        li.innerHTML="我是新来的移民li";
        ul.appendChild(li);
    }

//    //普通的绑定事件
//    for (var i = 0; i < ul.children.length; i++) {
//        ul.children[i].onclick = function () {
//            alert(this.innerHTML);
//        }
//    }

    //事件委托的绑定方式:
    //上面的普通绑定事件的不好的地方在于
    //由于js代码是从上往下执行的,
    // 事件绑定的这段代码执行完毕之后就不会再继续执行了
    //所以会导致后来新增加进去的 li 没有绑定那个事件
    //通过事件冒泡的方式进行事件委托,
    //可以实时的给新增加进来的li设置事件
    //其实并不是给li绑定事件,
    // 而是间接的给li设置了事件,
    // 相当于把li的事件委托给了ul
        ul.onclick = function (event) {
            //获取兼容性的事件对象
            event = event || window.event;

            //获取兼容性的第一个事件源对象
            var obj = event.target || event.srcElement;

            if(obj.tagName.toLocaleLowerCase()==="li"){
                alert(obj.innerHTML);
            }
        }

</script>
</body>
</html>


10.获取行内式、内嵌式、外链式的CSS样式的各种方式

◆获取对象的属性值的两种方式,第一种是对象.属性名,第二种是对象["属性名"],第二种非常的灵活,第一种比较准确。

◆获取行内式:对象.style.属性名和对象.style["属性名"],这种方式只能取行内的样式,这个style也是一个对象,它是页面标签中的style属性里的字符串转换成了json对象,如果你想获取页面标签中style属性的字符串,可以使用style.cssText来获取纯字符串。

◆获取内嵌式和外链式:对象.currentStyle.属性名和对象.currentStyle["属性名"]只能够在IE浏览器中使用,window.getComputedStyle(对象,伪元素对象).属性名和window.getComputedStyle(对象,伪元素对象)["属性名"]可以在IE9及以上的等一些主流浏览器中使用,如果没有伪元素对象可以给这个方法的参数赋值null,获取行内式的方式只能够获取行内式,但是获取内嵌式与外链式的方式其实还可以获取行内式的样式。

◆获取内嵌式与外链式的兼容性写法

if(window.getComputedStyle){
return window.getComputedStyle(element,null)["background-color"];
}else {
return element.currentStyle["background-color"];
}
◆获取外链式和内嵌式的css样式:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取外链式和内嵌式的css样式</title>
    <style type="text/css">
        #box {
            width: 200px;
            height: 200px;
            background-color: #901;
            position: fixed;
            /*left: 200px;*/
            top: 200px;
        }
    </style>
</head>
<body>
<div id="box" style="left:250px;background-color: #901;"></div>
<script>

    /**
     * 获取行内式、内嵌式、外链式的css样式的方式:
     *
     * 获取行内式:
     * 对象.style.属性名和对象.style["属性名"],
     * 这种方式只能取行内的样式,
     * 这个style也是一个对象,
     * 它是页面标签中的style属性里的字符串转换成了json对象,
     * 如果你想获取页面标签中style属性的字符串,
     * 可以使用style.cssText来获取纯字符串。
     *
     * 获取内嵌式和外链式:
     * 对象.currentStyle.属性名和对象.currentStyle["属性名"],
     * 只能够在IE浏览器中使用,
     * window.getComputedStyle(对象,伪元素对象).属性名
     * 和window.getComputedStyle(对象,伪元素对象)["属性名"]
     * 可以在IE9及以上的等一些主流浏览器中使用,
     * 如果没有伪元素对象可以给这个方法的参数赋值null,
     * 获取行内式的方式只能够获取行内式,
     * 但是获取内嵌式与外链式的方式
     * ★其实还可以获取行内式的样式。
     */
    console.log(box.style.left);
//    console.log(box.currentStyle.left);
    console.log(window.getComputedStyle(box, null).left);

    console.log(box.style.backgroundColor);//全部都可以获取
    console.log(box.style["backgroundColor"]);//全部都可以获取
    console.log(box.style["background-color"]);//全部都可以获取
    //    console.log(box.currentStyle.backgroundColor);//全部都可以获取
    console.log("1" + window.getComputedStyle(box, null)["backgroundColor"]);//全部都可以获取
    console.log("2" + window.getComputedStyle(box, null)["background-color"]);//全部都可以获取
    console.log("3" + window.getComputedStyle(box, null).backgroundColor);//全部都可以获取
    console.log(box.style);


    /**
     * 功能:获取兼容性的css样式对象
     * 其它:可以获取内嵌式、外链式、行内式的样式对象
     * @param element
     * @returns {*}
     */
    function getStyle(element) {
        return element.currentStyle ?
                element.currentStyle :
                window.getComputedStyle(element, null);
    }
</script>
</body>
</html>

◆无论是行内式的样式还是内嵌式外链式的样式,使用[]方括号的方式获取样式时,既可以使用驼峰命名法也可以使用-命名法,如box.style.backgroundColor即可以写成box.style["backgroundColor"]也可以写成box.style["background-color"]这样,都行,但是如果使用对象.的方式只能够使用驼峰命名法。

◆通过元素和属性名获取样式的属性值:内嵌式、外链式的CSS样式的兼容性写法

/**
     * 功能:获取该元素样式属性的属性值
     * @param element
     * @param attribute
     * @returns {*}
     */
    function getStyle(element, attribute) {
        return element.currentStyle
                ?
                element.currentStyle[attribute]
                :
                window.getComputedStyle(element, null)[attribute];
    }

但是,当页面使用ctrl+鼠标滚轮进行发大缩小时,会造成获取getStyle(element, key)获取的值有小数的。


11.匀速动画计算步长与缓速动画计算步长

◆匀速动画计算步长

element.speed =element.target > element.leader ? 10 : -10;

◆缓速动画计算步长

//获取步长
element.speed = (element.target- element.leader) / 10 || 0;     //二次计算步长
element.speed = element.speed > 0 ?Math.ceil(element.speed) : Math.floor(element.speed);


12.封装缓速动画框架

◆简单版

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>封装的兼容性样式对象制作缓速动画框架(简单版)</title>
    <style type="text/css">
        .box {
            height: 200px;
            background-color: #eee;
            position: relative;
            padding-left: 100px;
            padding-top: 20px;
        }

        #box1 {
            width: 80px;
            height: 80px;
            background-color: #701;
            position: absolute;
            top: 60px;
            left: 100px;
            /*box-shadow: #a01 0px 0px 80px 10px;*/
        }


    </style>
</head>
<body>
<div class="box">
    <button>移动到400</button>
    <button>移动到900</button>
    <div id="box1"></div>
</div>

<script>

    //需求:当点击按钮时,缓速移动
    //要求:必须使用封装的兼容性对象的方法  方法参数1:元素对象 方法参数2:要获取的属性名(单个属性)
    //思路:封装缓速移动的框架,多添加一个参数,attribute
    //步骤:
    //1.获取事件源及相关元素对象
    //2.绑定事件
    //3.书写事件驱动程序

    //1.获取事件源及相关元素对象
    var box = document.getElementsByTagName("div")[0];
    var btn = box.children[0];
    var btn2 = box.children[1];
    var box1 = box.children[2];
    //2.绑定事件
    btn.onclick = function () {
        //3.书写事件驱动程序
        animate(box1, "left", 400);
    }
    btn2.onclick = function () {
        //3.书写事件驱动程序
        animate(box1, "left", 900);
    }


        /**
         * 功能:获取该元素样式属性的属性值
         * @param element
         * @param attribute
         * @returns {*}
         */
        function getStyle(element, attribute) {
            return element.currentStyle
                    ?
                    element.currentStyle[attribute]
                    :
                    window.getComputedStyle(element, null)[attribute];
        }


    /**
     * 功能:缓速改变元素的属性(类似缓速移动或者改变大小的动画效果)
     * @param element
     * @param attribute
     * @param target
     */
    function animate(element, attribute, target) {
        //使用定时器之前先清除定时器
        clearInterval(element.timer);
        //使用定时器
        element.timer = setInterval(function () {
            //  获取当前的位置
            element.leader = parseInt(getStyle(element, attribute)) || 0;
            //获取步长
            element.speed = (target - element.leader) / 10 || 0;
            //二次计算步长
            element.speed = element.speed > 0 ?
                    Math.ceil(element.speed) : Math.floor(element.speed);
            //重新设置当前位置
            element.leader = element.leader + element.speed;

            //判断是否距离当前位置只有一步之遥了
            if (Math.abs(target - element.leader) <= Math.abs(element.speed)) {
                //直接到达指定目标位置
                element.style[attribute] = target + 'px';
                clearInterval(element.timer);
                return;
            }
            //进行移动
            element.style[attribute] = element.leader + "px";
        }, 30);
    }

</script>
</body>
</html>

◆中级版

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>封装的兼容性样式对象制作缓速动画框架(中级版)</title>
    <style type="text/css">
        .box {
            height: 200px;
            background-color: #eee;
            position: relative;
            padding-left: 100px;
            padding-top: 20px;
        }

        #box1 {
            width: 80px;
            height: 80px;
            background-color: #701;
            position: absolute;
            top: 60px;
            left: 100px;
            /*box-shadow: #a01 0px 0px 80px 10px;*/
        }


    </style>
</head>
<body>
<div class="box">
    <button>开始动画</button>
    <div id="box1"></div>
</div>

<script>

    //需求:当点击按钮时,缓速移动
    //要求:必须使用封装的兼容性对象的方法  方法参数1:元素对象 方法参数2:参数对象(多个属性)
    //思路:封装缓速移动的框架,多添加一个参数,attribute
    //步骤:
    //1.获取事件源及相关元素对象
    //2.绑定事件
    //3.书写事件驱动程序

    //1.获取事件源及相关元素对象
    var box = document.getElementsByTagName("div")[0];
    var btn = box.children[0];
    var box1 = box.children[1];
    //2.绑定事件
    btn.onclick = function () {
        //3.书写事件驱动程序
        var json = {width: 200.3, height: 200.3, left: 400.3, height: 400.3};
        animate(box1, json);
    }


    /**
     * 功能:获取该元素样式属性的属性值
     * @param element
     * @param attribute
     * @returns {*}
     */
    function getStyle(element, attribute) {
        return element.currentStyle
                ?
                element.currentStyle[attribute]
                :
                window.getComputedStyle(element, null)[attribute];
    }


    //缓速改变元素的属性(类似缓速移动或者改变大小的动画效果)
    function animate(element, json) {
        //使用定时器之前先清除定时器
        clearInterval(element.timer);
        //使用定时器
        element.timer = setInterval(function () {
            //开闭思想
            var bool = true;

            //遍历json对象 完成每一个属性的缓速动画效果
            for (var key in json) {
                //key作为属性名  json[key]作为目标属性值

                //bug:当页面使用ctrl+鼠标滚轮进行发大缩小时,
                // 会造成获取getStyle(element, key)获取的值有小数,
                //或者你传递进来的数值带有小数,那么就可能会造成死循环
                //因为parseInt是向下取整的,所以不能那样子,只能够向上取整
                var str = getStyle(element, key)
                var index = str.indexOf("px");
                str = str.slice(0, index);

                //  获取当前的位置
                element.leader = Math.ceil(str) || 0;
                //获取步长
                element.speed = (json[key] - element.leader) / 10 || 0;
                //二次计算步长
                element.speed = element.speed > 0 ?
                        Math.ceil(element.speed) : Math.floor(element.speed);



                //只要有一个位置不是指距离一步之遥
                if (Math.abs(json[key] - element.leader) <= Math.abs(element.speed)) {
                    element.style[key] = json[key] + 'px';
                    continue;
                } else {
                    bool = false;
                }
                //进行移动
                element.style[key] = (element.leader + element.speed) + "px";
            }
            console.log(1);
            if (bool) {
//                //直接到达指定目标位置
                clearInterval(element.timer);
            }
        }, 30);
    }

</script>
</body>
</html>

◆高级版

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>封装的兼容性样式对象制作缓速动画框架(高级版)</title>
    <style type="text/css">
        .box {
            height: 200px;
            background-color: #eee;
            position: relative;
            padding-left: 100px;
            padding-top: 20px;
        }

        #box1 {
            width: 80px;
            height: 80px;
            background-color: #701;
            position: absolute;
            top: 60px;
            left: 100px;
            /*box-shadow: #a01 0px 0px 80px 10px;*/
        }


    </style>
</head>
<body>
<div class="box">
    <button>走你,再回来</button>
    <div id="box1" style="border-radius: 0px 5px 6px 7px;"></div>
</div>

<script>

    //需求:当点击按钮时,缓速移动
    //要求:必须使用封装的兼容性对象的方法  方法参数1:元素对象 方法参数2:参数对象(多个属性)
    //新增要求:增加回调用函数,当动画结束后执行回调用函数
    //思路:封装缓速移动的框架,多添加一个参数,attribute
    //步骤:
    //1.获取事件源及相关元素对象
    //2.绑定事件
    //3.书写事件驱动程序

    //1.获取事件源及相关元素对象
    var box = document.getElementsByTagName("div")[0];
    var btn = box.children[0];
    var box1 = box.children[1];
    //2.绑定事件
    btn.onclick = function () {
        //3.书写事件驱动程序
        var json ={"border-radius":50} //{width: 200.3, height: 200.3, left: 400.3, top: 400.3};
        var json2 = {width: 80.3, height: 80.3, left: 100.5, top: 60.6};
        //执行完动画后再执行回调函数
        animate(box1, json, function () {
          //  animate(box1, json2, null);
        });
    }


    /**
     * 功能:获取该元素样式属性的属性值
     * @param element
     * @param attribute
     * @returns {*}
     */
//    function getStyle(element, attribute) {
//        return element.currentStyle
//                ?
//                element.currentStyle[attribute]
//                :
//                window.getComputedStyle(element, null)[attribute];
//    }
    function getStyle(element, attribute) {
        return (element.currentStyle
                ?
                element.currentStyle[attribute]
                :
                window.getComputedStyle(element, null)[attribute])
                ||
                element.style[attribute];
    }


    //缓速改变元素的属性(类似缓速移动或者改变大小的动画效果)
    function animate(element, json, fn) {
        //使用定时器之前先清除定时器
        clearInterval(element.timer);
        //使用定时器
        element.timer = setInterval(function () {
            //开闭思想
            var bool = true;

            //遍历json对象 完成每一个属性的缓速动画效果
            for (var key in json) {
                //key作为属性名  json[key]作为目标属性值

                //bug:当页面使用ctrl+鼠标滚轮进行发大缩小时,
                // 会造成获取getStyle(element, key)获取的值有小数,
                //或者你传递进来的数值带有小数,那么就可能会造成死循环
                //因为parseInt是向下取整的,所以不能那样子,只能够向上取整
                var str = getStyle(element, key)
                var index = str.indexOf("px");
                str = str.slice(0, index);

                //  获取当前的位置
                element.leader = Math.ceil(str) || 0;
                //获取步长
                element.speed = (json[key] - element.leader) / 10 || 0;
                //二次计算步长
                element.speed = element.speed > 0 ?
                        Math.ceil(element.speed) : Math.floor(element.speed);


                //只要有一个位置不是指距离一步之遥 这么做事考虑到了小数的情况
                if (Math.abs(json[key] - element.leader) <= Math.abs(element.speed)) {
                    element.style[key] = json[key] + 'px';
                    continue;
                } else {
                    bool = false;
                }
                //进行移动
                element.style[key] = (element.leader + element.speed) + "px";
            }
            console.log(1);
            if (bool) {
//                //直接到达指定目标位置
                clearInterval(element.timer);

//                //执行完毕后 执行回掉函数
                if (fn) {
                    fn();
                }
            }
        }, 18);
    }

</script>
</body>
</html>


13.使用封装的缓速框架来DIY动画效果:手风琴效果+360开机动画

◆使用dom简单封装的jquery:

 /* 功能:显示元素
 * @param element
 */
function show(element) {
    element.style.display = "block";
}

/**
 * 功能:隐藏元素
 * @param element
 */
function hide(element) {
    element.style.display = "none";
}

/**
 * 功能:最强的缓速移动方法
 * 参数:传递元素对象、传递样式参数对象、传递回掉函数
 * @param element
 * @param json
 * @param fn
 */
function animate(element, json, fn) {
    //使用定时器之前先清除定时器
    clearInterval(element.timer);
    //使用定时器
    element.timer = setInterval(function () {
        //开闭思想
        var bool = true;

        //遍历json对象 完成每一个属性的缓速动画效果
        for (var key in json) {
            //key作为属性名  json[key]作为目标属性值

            //bug:当页面使用ctrl+鼠标滚轮进行发大缩小时,
            // 会造成获取getStyle(element, key)获取的值有小数,
            //或者你传递进来的数值带有小数,那么就可能会造成死循环
            //因为parseInt是向下取整的,所以不能那样子,只能够向上取整
            //var str = getStyle(element, key)
            //var index = str.indexOf("px");
            //str = str.slice(0, index);

            //element.str= getStyle(element, key).slice(0,getStyle(element, key).indexOf("px"))

            //  获取当前的位置
            element.leader = Math.ceil(getStyle(element, key).replace("px", "")) || 0;


            //获取步长
            element.speed = (json[key] - element.leader) / 10 || 0;
            //二次计算步长
            element.speed = element.speed > 0 ?
                Math.ceil(element.speed) : Math.floor(element.speed);

            匀速的步长计算
            //element.speed = json[key] > element.leader ? 10 : -10;


            //只要有一个位置不是指距离一步之遥 这么做事考虑到了小数的情况
            if (Math.abs(json[key] - element.leader) <= Math.abs(element.speed)) {
                element.style[key] = json[key] + 'px';
                continue;
            } else {
                bool = false;
            }
            //进行移动
            element.style[key] = (element.leader + element.speed) + "px";
        }
        console.log(1)
        if (bool) {
//                //直接到达指定目标位置
            clearInterval(element.timer);

//                //执行完毕后 执行回掉函数
            if (fn) {
                fn();
            }
        }
    }, 18);
}

/**
 * 功能:垂直方向上缓度滚动到某个位置
 * 参数说明:element元素对象  target指定位置
 * @param element
 * @param target
 */
function scrollAnimateY(element, target) {
    //使用定时器之前先清除定时器
    clearInterval(element.timer);
    //设置定时器
    element.timer = setInterval(function () {

        //计算步长
        element.speed = (target - element.leader) / 10;
        //二次计算步长    防止 水永远取不尽 定时器永远不停
        element.spend = element.spend > 0 ? Math.ceil(element.spend) : Math.floor(element.spend);

        //距离是否只剩一步之遥
        if (Math.abs(target - element.leader) <= Math.abs(element.speed)) {
            window.scrollTo(0, target);
            console.log(element.leader);
            clearInterval(element.timer);
            return;
        }
        //设置移动的动画
        window.scrollTo(0, element.leader + element.speed);
    }, 30);
}

/**
 * 功能:水平方向的元素缓速移动的动画
 * @param element
 * @param target
 */
function animateX(element, target) {
    //绑定计时器之前先清除定时器
    clearInterval(element.timer);
    element.timer = setInterval(function () {

        //注意:this.offsetLeft最终获取的是number类型的值,并且它还会对小数进行四舍五入,
        //如果this.style.left中有小数,并且还低于0.5,那么就会导致offsetLeft每次获取到的值,
        //都是一样,然后就会造成 盒子不懂,定时器不停的现象发生,所以缓速动画时要记得给步长取整
        // 如果步长>0就向上取整,避免步长小于0.5时出现bug,
        // 如果步长<0,就向下取整,避免步长下雨-0.5时出现bug。


        //每次移动的步长
        element.spend = (target - element.offsetLeft) / 10

        //对步长进行取整,避免offsetLeft底层的四舍五入的影响
        element.spend = element.spend > 0 ? Math.ceil(element.spend) : Math.floor(element.spend);


        //目标位置减去当前位置的绝对值 如果小于步长的绝对值 那么就说明也就一步之遥了,
        // 那么直接移动到指定的位置清除计时器算了。
        if (Math.abs(target - element.offsetLeft) <= Math.abs(element.spend)) {

            element.style.left = target + "px";
            clearInterval(element.timer);
            return;
        }

        //重新设置距离左边的位置
        element.style.left = element.offsetLeft + element.spend + "px";
        console.log(element.style.left)
    }, 30);
}

/**
 * 功能:垂直方向的元素缓速移动的动画
 * @param element
 * @param target
 */
function animateY(element, target) {
    //绑定计时器之前先清除定时器
    clearInterval(element.timer);
    element.timer = setInterval(function () {

        //注意:this.offsetTop最终获取的是number类型的值,并且它还会对小数进行四舍五入,
        //如果this.style.Top中有小数,并且还低于0.5,那么就会导致offsetTop每次获取到的值,
        //都是一样,然后就会造成 盒子不懂,定时器不停的现象发生,所以缓速动画时要记得给步长取整
        // 如果步长>0就向上取整,避免步长小于0.5时出现bug,
        // 如果步长<0,就向下取整,避免步长下雨-0.5时出现bug。


        //每次移动的步长
        element.spend = (target - element.offsetTop) / 10

        //对步长进行取整,避免offsetTop底层的四舍五入的影响
        element.spend = element.spend > 0 ? Math.ceil(element.spend) : Math.floor(element.spend);


        //目标位置减去当前位置的绝对值 如果小于步长的绝对值 那么就说明也就一步之遥了,
        // 那么直接移动到指定的位置清除计时器算了。
        if (Math.abs(target - element.offsetTop) <= Math.abs(element.spend)) {
            element.style.top = target + "px";
            clearInterval(element.timer);
            return;
        }

        //重新设置距离左边的位置
        element.style.top = element.offsetTop + element.spend + "px";
        console.log(element.style.top)
    }, 10);
}

/**
 * 功能:获取兼容性的css样式对象的样式属性值
 * 其它:可以获取内嵌式、外链式、行内式的样式对象的样式属性值
 * @param element
 * @returns {*}
 */
//function getStyle(element, attribute) {
//    return element.currentStyle ?
//        element.currentStyle[attribute] :
//        window.getComputedStyle(element, null)[attribute];
//}
function getStyle(element, attribute) {
    return (element.currentStyle
            ?
            element.currentStyle[attribute]
            :
            window.getComputedStyle(element, null)[attribute])
        ||
        element.style[attribute];
}


/**
 * 功能:用来检测浏览器可视区域的兼容性的client对象
 * @returns {{width: (Number|number), height: (Number|number)}}
 */
function client() {

    return {
        width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
        height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
    }
}

/**
 * 功能:获取scroll对象
 * @returns {*}
 */
function scroll() {
    /*
     *注意事项:
     *1.无论有没有声明DTD 在IE9及以上的所有浏览器都支持window.pageXOffset和window.pageYOffset
     * 但是在IE9以下不支持,并且会返回undefined。
     *2.在没有声明DTD时 在IE9以上的所有浏览器都支持document.body.scrollLeft和document.body.scrollTop
     * 在声明了DTD时 所有浏览器都不支持,并且会返回0
     *3.在声明了DTD时 所有浏览器都支持document.documentElement.scrollLeft和document.documentElement.scrollTop
     * 无论有没有声明DTD IE浏览器都支持,没有声明DTD 其它除了IE浏览器外都不支持,并且会返回0。
     * */
    //判断是否不为undefined
    if (window.pageXOffset !== "undefined" || window.pageYOffset !== "undefined") {
        //返回一个关于scroll的对象回去
        return {scollLeft: window.pageXOffset, scollTop: window.pageYOffset};
    }
    else if (document.compatMode === "BackCompa") {//是否没有声明DTD(<!DOCTYPE html>或者其它<html>标签之上的标记)
        //判断是否是IE浏览器
        if (document.documentElement.scrollLeft || document.documentElement.scrollTop) {
            return {scollLeft: document.documentElement.scrollLeft, scollTop: document.documentElement.scrollTop};
        }
        else {//如果不是IE浏览器
            return {scollLeft: document.body.scrollLeft, scollTop: document.body.scrollTop};
        }
    }
    else {//如果声明了DTD
        return {scollLeft: document.documentElement.scrollLeft, scollTop: document.documentElement.scrollTop};
    }

//        //精简版封装只需要返回 这个就是上面判断的精简 效果一样
//        return {
//            scollLeft: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft,
//            scollTop: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
//        }
}

/**
 * 功能:根据 传递参数 返回相应的对象
 * 说明:参数为:#id选择器、.class选择器、tag普通选择器其中一种
 * @param str
 * @returns {*}
 */
function $(str) {
    //获取头部选择符
    var head = str.charAt(0);
    //去除id选择器与class选择器标识后的内容
    var body = str.slice(1);
    if (head === "#") { //id
        return document.getElementById(body);
    } else if (head === ".") {//class
        return document.getElementsByClassName(body);
    } else {//tag
        return document.getElementsByTagName(str);
    }
}


//******************获取子元素节点*********开始********//
/**
 * 功能:获取第一个子元素节点
 * @param ele
 * @returns {Element|*|Node}
 */
function getfirstchild(ele) {
    return ele.firstElementChild || ele.firstChild;
}

/**
 * 功能:获取最后一个子元素节点
 * @param ele
 * @returns {Element|*|Node}
 */
function getlastchild(ele) {
    return ele.lastElementChild || ele.lastChild;
}

/**
 * 功能:获取对应索引值的子元素节点
 * @param ele
 * @param index
 * @returns {*|HTMLElement}
 */
function getchildofindex(ele, index) {
    return ele.children[index];
}

/**
 * 功能:获取所有的子元素节点
 * @param ele
 * @returns {Array}
 */
function getallchild(ele) {
    var newArr = [];
    var oldArr = ele.children;//childNodes;
    for (var i = 0; i < oldArr.length; i++) {
        if (oldArr[i].nodeType === 1) {
            newArr.push(oldArr[i]);
        }
    }
    return newArr;
}
//******************获取子元素节点*********结束********//


//******************获取兄弟元素节点*********开始********//
/**
 * 功能:获取上一个兄弟元素节点
 * @param ele
 * @returns {Element|*|Node}
 */
function getpresibling(ele) {
    var pre = ele.previousElementSibling || ele.previousSibling;
    return pre;
}

/**
 * 功能:获取下一个兄弟元素节点
 * @param ele
 * @returns {Element|*|Node}
 */
function getnextsibling(ele) {
    return ele.nextElementSibling || ele.nextSibling;
}

/**
 * 功能:获取对应索引值的兄弟元素节点
 * @param ele
 * @param index
 * @returns {*|HTMLElement}
 */
function getsiblingofindex(ele, index) {
    return ele.parentNode.children[index];
}


/**
 * 功能:获取所有的兄弟元素节点(不包括自己)
 * @param ele
 * @returns {Array}
 */
function getallsibling(ele) {
    var newArr = [];
    var oldArr = ele.parentNode.children;
    for (var i = 0; i < oldArr.length; i++) {
        if (oldArr[i] != ele) {
            newArr.push(oldArr[i]);
            //newArr[newArr.length]=oldArr[i];
        }
    }
    return newArr;
}
//******************获取兄弟元素节点*********结束********//

◆手风琴效果:图片大小为1226*640

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用封装的样式缓速框架制作手风琴</title>
    <style type="text/css">
        body, ul, li, div {
            padding: 0;
            margin: 0;
        }

        .box {
            width: 1150px;
            height: 400px;
            border: 1px solid #b01;
            margin: 50px auto;
            overflow: hidden;
        }

        ul {
            width: 120%;
        }

        li {
            width: 240px;
            height: 400px;
            float: left;
            list-style: none;
        }
    </style>
</head>
<body>
<div class="box">
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>
<script src="13.自己封装的query1.0.0.3.js"></script>
<script>
    //需求:动态给每一个li设置背景图片,当移入到一张图片上时当前图片变宽,其它图片就变窄
    //思路:循环给每一个li设置背景,循环遍历li,当移入一个li时,就循环变窄全部,然后再变宽自己
    //注意点:由于是缓速动画,所以可能会造成抖动的现象
    //步骤:
    //1.获取事件源及相关对象
    //2.绑定事件
    //3.书写事件驱动程序

    //1.获取事件源及相关对象
    var box = document.getElementsByTagName("div")[0];
    var ul = box.children[0];
    var liArr = ul.children;

    for (var i = 0; i < liArr.length; i++) {
        liArr[i].style.background = "url(images/" + (i + 1) + ".jpg) no-repeat scroll left top";
    }

    //2.绑定事件  使用事件委托的方式
    ul.onmouseover = function (event) {
        //3.书写事件驱动程序

        //获取兼容性的事件对象
        event = event || window.event;
        //获取兼容性的 事件源对象
        var obj = event.target ? event.target : event.srcElement;
        if (obj.tagName.toLowerCase() === "li") {
            for (var i = this.children.length - 1; i >= 0; i--) {
                if (obj !== this.children[i]) {

                    animate(this.children[i], {width: 100});//先把别的变窄

//                    this.children[i].style.width = "100px";

                } else {

                    animate(obj, {width: 800});//把移入的li变宽

//                    obj.style.width = "800px";
                }
            }
        }
        console.log(this);
    }
    ul.onmouseout = function () {
        for (var i = 0; i < this.children.length; i++) {
            animate(this.children[i], {width: 240});//先把所有恢复原样
        }
    }

</script>

</body>
</html>

◆360开机动画:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模拟360开机动画缓速退出</title>
    <style>
        .box {
            width: 322px;
            position: fixed;
            bottom: 0;
            right: 0;
        }

        span {
            position: absolute;
            top: 0;
            right: 0;
            width: 30px;
            height: 20px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div class="box">
    <span id="guanbi"></span>
    <div class="hd" id="t">
        <img src="https://img-blog.csdnimg.cn/2022010620572986805.jpeg" alt=""/>
    </div>
    <div class="bd" id="b">
        <img src="https://img-blog.csdnimg.cn/2022010620573043566.jpeg" alt=""/>
    </div>
</div>
<script src="13.自己封装的query1.0.0.3.js"></script>
<script>
    //需求:点击右上角的x号时,先向下缓慢移动,再向右缓慢移动
    //思路:获取x号,头部,底部对象,box盒子对象当点击x号时,
    //      底部的高度缓速变成0,整个box宽度缓速变成0
    //步骤:
    //1.获取事件源及相关元素对象
    //2.绑定事件
    //3.书写事件驱动程序

    //1.获取事件源及相关元素对象
    var box = document.body.firstElementChild || document.body.firstChild;
    var guanbi = box.children[0];
    var hd = box.children[1];
    var bd = box.children[2];

    //2.绑定事件
    guanbi.onclick = function () {
        //3.书写事件驱动程序
        animate(bd, {height: 0}, function () {
            animate(box, {width: 0});
        });
    }
</script>
</body>
</html>

转载于:https://www.cnblogs.com/jwlLWJ2018/p/9247736.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值