栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > Html/CSS > CSS教程

手风琴效果-原生JS

CSS教程 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

手风琴效果-原生JS

酷炫的手风琴效果

手风琴效果的特点:每次只展开一个元素,其他的兄弟元素都闭合

先从样式和布局开始,做一个原生JS的手风琴效果

html:

    1

    2

    3

    4

 css:

.c{    background-color: black;
}.c::before,.c::after{    content: '';    display: table;
}.c::after{    clear: both;
}.red{    width: 100px;    background-color:red;    float: left;    height: 300px;
}.blue{    background-color:blue;
}.green{    background-color: green;
}.yellow{    background-color: yellow;
}.yellow,.green,.blue{    width: 20px;    float: left;    height: 300px;
}

效果如图:

写完结构和样式,对JS要完成的效果进行拆解

需求分析:当鼠标点击一个元素时,对应元素的宽度变大,兄弟元素中宽度最大的元素宽度变小

实践:

1.首先,手风琴的效果要动起来,在JS中能够动起来的只有计时器,因此这里会用到周期性计时器,这一步可以后写,先进行第二步

如果你回到这里,恭喜你,已经完成了一半

问题:何时停掉计时器,停计时器要写在计时器函数中,满足条件时清除计时器

+(function () {    //查找元素
    var c = document.querySelector('.c');    var ps = document.querySelectorAll('.c p');    //绑定事件:事件的对象是其中一个p元素,给每个p元素绑定事件
    for (var i = 0; i < ps.length; i++) {        //需求的第一个元素:被点击的元素
        var p = ps[i];


        p. = function () {            //需求的第二个元素:兄弟中最大的元素
            for (var j = 0; j < ps.length; j++) {                if(getComputedStyle(ps[j]).width=='100px'){                    var obj = ps[j];                    break;
                }
            }            if(parseInt(getComputedStyle(this).width)==20){                //添加计时器
                var timer = setInterval(move,100);                var step = 10;                var that = this;                function move() {                    if(parseInt(getComputedStyle(that).width)<100){                        //点击的当前元素宽度变大
                        that.style.width = parseInt(getComputedStyle(that).width) + step + 'px';
                        obj.style.width = parseInt(getComputedStyle(obj).width) - step + 'px';                        console.log(getComputedStyle(that).width);
                    }else{
                        clearInterval(timer);
                    }

                }

            }

        }
    }
})();

问题:如果一次元素的宽度尚未到达20px,又去点击另一个元素,这时两个元素会同时动,

解决:让一个动作完成再执行另一个动作

分析:判断另一个动作是否要执行时在执行前判断的,所以在事件之外定义一个布尔全局变量

+(function () {    //查找元素
    var c = document.querySelector('.c');    var ps = document.querySelectorAll('.c p');    //绑定事件:事件的对象是其中一个p元素,给每个p元素绑定事件
    for (var i = 0; i < ps.length; i++) {        //需求的第一个元素:被点击的元素
        var p = ps[i];        var flag = true;

        p. = function () {            if(flag){
                flag = false;                //需求的第二个元素:兄弟中最大的元素
                for (var j = 0; j < ps.length; j++) {                    if(getComputedStyle(ps[j]).width=='100px'){                        var obj = ps[j];                        break;
                    }
                }                if(parseInt(getComputedStyle(this).width)==20){                    //添加计时器
                    var timer = setInterval(move,100);                    var step = 10;                    var that = this;                    function move() {                        if(parseInt(getComputedStyle(that).width)<100){                            //点击的当前元素宽度变大
                            that.style.width = parseInt(getComputedStyle(that).width) + step + 'px';
                            obj.style.width = parseInt(getComputedStyle(obj).width) - step + 'px';                            console.log(getComputedStyle(that).width);
                        }else{
                            clearInterval(timer);
                            flag = true;
                        }

                    }

                }
            }
        }
    }
})();

2.从需求来看,这里需要一个事件,事件的三要素:元素、事件、函数

元素:被点击的元素和兄弟元素中最大的那个(两个)

事件:click

函数:匿名函数

函数的功能:①点击的当前元素:如果宽度为20px,变为100px;否则,不变

+(function () {    //查找元素
    var c = document.querySelector('.c');    var ps = document.querySelectorAll('.c p');    //绑定事件:事件的对象是其中一个p元素,给每个p元素绑定事件
    for (var i = 0; i < ps.length; i++) {        //需求的第一个元素:被点击的元素
        var p = ps[i];        //需求的第二个元素:兄弟中最大的元素
        for (var j = 0; j < ps.length; j++) {            if(getComputedStyle(ps[j]).width=='100px'){                var obj = ps[j];                break;
            }
        }
        
        p. = function () {            console.log("我执行了");            //点击的当前元素宽度变大
            if(getComputedStyle(this).width=='20px'){                this.style.width = 100 + 'px';
                obj.style.width = 20 + 'px';
            }

        }
    }
})();

代码到这里遇到一个问题:除了初始设置默认值100px的那个元素,以后的元素宽度都不会再变回20px

分析:兄弟中最大的元素除了默认值之外,都是点击事件发生后才产生的,上面的代码只在初始时获得一次,点击后产生的最大兄弟元素并没有获得,因此,查找兄弟中最大的元素应该放在事件处理函数中

更新代码:

+(function () {    //查找元素
    var c = document.querySelector('.c');    var ps = document.querySelectorAll('.c p');    //绑定事件:事件的对象是其中一个p元素,给每个p元素绑定事件
    for (var i = 0; i < ps.length; i++) {        //需求的第一个元素:被点击的元素
        var p = ps[i];


        p. = function () {            //需求的第二个元素:兄弟中最大的元素
            for (var j = 0; j < ps.length; j++) {                if(getComputedStyle(ps[j]).width=='100px'){                    var obj = ps[j];                    break;
                }
            }            
            //点击的当前元素宽度变大
            if(getComputedStyle(this).width=='20px'){                this.style.width = 100 + 'px';
                obj.style.width = 20 + 'px';
            }

        }
    }
})();

此时,测试没有问题,接下来给代码添加动画,回到第一步

                      


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/242574.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号