小言_互联网的博客

jQuery动画案例——手风琴、选项卡(点餐)、图片轮播

272人阅读  评论(0)

注意:为了防止用户操作过快,导致动画叠加。在每一次新的动画前都需要调用stop()方法

1、 手风琴1

效果描述:每次点击一张图片,放置图片的父容器的宽从小逐渐变大。图片从垂直居中位置逐渐被拉开且前一张图片逐渐消失,被点击父容器内的图片逐渐出现。

效果图:

思路

由于每次点击一张图片,放置图片的父容器的宽从小逐渐变大。图片从垂直居中位置逐渐被拉开,故只需要使用自定义动画改变图片的高、放置图片父容器div的宽、图片的位置、图片的透明度即可。
每次点击不同div都要重新设置所有div的高、宽和left

  1. 最开始时先给每一个div父容器设置data-index,该值为每一个父容器对应的索引值。
  2. 将所有操作封装成函数setWAndH(indexTemp),该函数的参数为当前显示的图片的父容器的index(故之后点击每一个div时将其data-index传入函数)
  3. setWAndH(indexTemp)函数中进行设置每一个div的宽、高以及每一个div的位置(通过遍历(each()函数)实现), 如果当前遍历的元素的index与indexTemp相等,则当前元素为显示元素,故将其宽设置为800,反之设置为60。由于所有div的高是呈阶梯状,当前显示图片的高为500,其余元素的高与其自身index相关(500-Math.abs(indexTemp-index)*22(22为每个相邻div高的差值))。所有索引小于等于indexTemp元素的left都相差60,而大于indexTemp的元素需要在原来计算的left的基础上加上显示div的宽(即800)
  4. setWAndH(indexTemp)函数中还要设置显现div的子元素图片的高、透明度及位置(注意:此设置需要以自定义动画的方式呈现),图片由最初的高度为0,不透明度为0以及top为50%变为高为父容器的100%,不透明度为1,top为0。非显示元素做与上述相反操作。
完整代码
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .all {
            position: relative;
            line-height: 424px;
            width: 1000px;
            height: 424px;
            margin: 200px;
        }

        .all > div {
            position: absolute;
            border: 1px solid silver;
            background: #ebffc6;
            top: 0;
            bottom: 0;
            margin: auto;
        }
        .all>div>span{
            position: absolute;
            display: inline-block;
            width: 100%;;
            text-align: center;
        }
        img {
            position: absolute;
            width: 100%;
            height: 0;
            top: 50%;
        }
    </style>
</head>
<body>
<div class="all">
    <div>
        <span>1</span><img src="img/t1.png"/>
    </div>
    <div>
        <span>2</span><img src="img/t2.png"/>
    </div>
    <div>
        <span>3</span><img src="img/t3.png"/>
    </div>
    <div data-index="3">
        <span>4</span><img src="img/t4.png"/>
    </div>
    <div>
        <span>5</span><img src="img/t5.png"/>
    </div>
    <div>
        <span>6</span><img src="img/t6.png"/>
    </div>
    <div>
        <span>7</span><img src="img/t7.png"/>
    </div>
</div>
</body>
<script src="js/jquery-1.9.1.js"></script>
<script src="js/jquery-3.0.0.js"></script>
<script>
    //只需要变化图片的高以及div的宽即可。
    $(function () {
        setWAndH($(".all>div:nth-of-type(4)").attr("data-index"));
        $(".all>div").on("click",function(){
            setWAndH($(this).attr("data-index"))
        });
        function setWAndH(indexTemp) {
            $(".all>div").each(function (index) {
                //设置宽
               if(!$(this).attr("data-index")){
                   $(this).attr("data-index",index);
               }
                var leftTemp =0;
                if(indexTemp==index){
                    leftTemp = index*60;
                    $(this).stop(false,true).animate({
                        width:800,
                        height:500-Math.abs(indexTemp-index)*22,
                        left:leftTemp
                    }).children("img").stop(false,true).animate({
                        height: "100%",
                        opacity: 1,
                        top: 0
                    },300)
                }else{
                    if(index>indexTemp){
                        leftTemp = (index-1)*60+800
                    }else{
                        leftTemp = index*60
                    }
                    $(this).stop(false,true).animate({
                        width:60,
                        height:500-Math.abs(indexTemp-index)*32,
                        left:leftTemp
                    }).children("img").stop(false,true).animate({
                        height: 0,
                        opacity: 0,
                        top: "50%"
                    }, 300);
                }
                //设置高
            })
        }
    })
</script>
</html>
2. 手风琴2

点击一个li,该li中的ul显示,其余liul隐藏。默认情况下第一个liul显示,其余liul隐藏。
直接使用slideDown()和slideUp()即可

效果图

完整代码
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<style>
    *{
        margin:0;
        padding:0
    }
    li{
        list-style:none
    }
    a{
        text-decoration:none
    }
    .main>a{
        display: inline-block;
        height: 30px;
        width: 240px;
        background: -webkit-linear-gradient(top, #6c6e74 0%, #4b4d51 100%);
        color:white;
        text-align:center;
    }
    .main>ul>li{
        height: 30px;
        width: 240px;
        background:#e5e5e5;
        text-align:center;
        color:#999;
        border-bottom: 1px solid silver;
    }
    .all{
        width: 300px;
        margin:auto
    }
    .back{
        background: -webkit-linear-gradient(top, #a5cd4e 0%, #6b8f1a 100%) !important;
    }
    .show{
        display: block;
    }
    .menu{
        display: none;
    }
</style>
<body>
<ul class="all">
    <li class="main">
        <a class="back">菜单一</a>
        <ul class="show">
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </li>
    <li class="main">
        <a>菜单二</a>
        <ul class="menu">
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    </li>
    <li class="main">
        <a>菜单三</a>
        <ul class="menu">
            <li>1</li>
        </ul>
    </li>
    <li class="main">
        <a>菜单四</a>
        <ul class="menu">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </li>
    <li class="main">
        <a>菜单五</a>
        <ul class="menu">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
        </ul>
    </li>
</ul>
</body>
<script src="js/jquery-3.0.0.js"></script>
<script src="js/jquery-1.9.1.js"></script>
<script>
    $(function(){
        $(".main>a").each(function (index) {
            $(this).click(function () {
                $(this).siblings().removeClass().stop(false,true).slideDown().parent().siblings().find("ul").stop(false,true).slideUp();
                $(this).addClass("back").parent().siblings().find("a").removeClass();
            })
        })
    })
</script>
</html>
3. 选项卡(点餐)

效果描述:实现类似美团的点餐功能。当点击左边种类区时,右边会滑动至对应的种类区域最顶部。当滑动右边饭菜集合时,左边种类区也会切换到相应的位置。

效果图:

思路解析
  1. 当点击左边种类模块时,可通过点击index值计算右边滚动区域的scrollTop,具体计算方法:用该index对应的右边区域模块的position中的top值(即相对于父元素顶部的距离)加上当前右边滚动区域的scrollTop,即为点击模块对应的右边区域最顶部。
  2. 当滑动右边滚动区域时,可通过遍历右边滚动区域的所有ul,判断其position().top<=0并且Math.abs($(this).position().top)<= $(this).height()来确定当前可视区域对应的左边的index此处右边的每个ulindex值与左边可点击的每个模块的index值是对应的
  3. 当点击左边的模块的index值大于等于左边div的个数的一半时,将左边滚动区域的scrollTop设置为滚动区域总高-可视区域高,当小于时,将左边滚动区域的scrollTop设置为0
编写代码过程中遇到的问题

① 由于点击左边模块时,右边滚动区域会滚动,而右边滚动会重新设置左边选中模块。此时会出现左边选中模块一直切换的现象,直到右边滚动结束。此时可在点击左边某个模块后,右边滚动区域滚动结束前将右边滚动区域的滚动事件移除。在动画结束后再次绑定滚动事件。
② 在①中,在动画结束后绑定了滚动事件,虽然scrollTop在意义上以及不再会改变了,但是仍会调用几次右边滚动事件(未解决(并不知道为啥,但不影响效果))。
③ 滚动事件在遍历的过程中,实际上会有两个index符合if判断(临界值的锅)。正确index以及正确index的前一个index。但是由于遍历是从小到大遍历的,最终的结果还是正确的。

一些注意事项

① 当想要htmlbody与整个屏幕一样宽、高时,需设置html,body{width:100%;height:100%;}
② 当设置上下模块分别占不同比例时,设置margin可能会导致一些错误。故可再添加一个顶部div,当顶部和底部div分别占页面的不同比例。
③ 当想要将滚动轴隐藏起来时,可将可滚动元素的宽稍微设置大一些。且给其父元素设置overflow:hidden,则可实现。

完整代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
    <title>点外卖</title>
</head>
<style>
    *{
        margin:0;
        padding:0;
        box-sizing: border-box;
    }
    html, body {
        width: 100%;
        height: 100%;
        overflow: hidden;
    }
    .header{
        height: 30%;
    }
    .all{
        display:flex;
        width: 100%;
        height: 70%;
        overflow: hidden;
    }
    .leftOuter{
        border:1px solid silver;
        flex:1;
        overflow: hidden;
    }
    .rightOuter{
        border:1px solid silver;
        flex: 3;
        overflow: hidden;
        position: relative;
    }
    .leftInner{
        width: 110%;
        overflow-y:scroll;
        height: 100%;
    }
    .rightInner{
        width: 110%;
        overflow-y:scroll;
        height: 100%;
    }
    .left,.right{
        display: flex;
        flex-direction: column;
    }
    .left{
        height: 130%;
    }
    li{
        list-style: none;
    }
    .left>div{
        flex: 1;
        line-height: 100px;
        text-align: center;
        border-bottom: 1px solid silver;
    }
    .right>ul>li{
        height: 75px;
        line-height: 75px;
        text-align: center;
        border-bottom: 1px solid silver;
    }
    .selectItem{
        background: #cd94ff;
        color:white
    }
</style>
<body>
<div class="header"></div>
<div class="all">
    <div class="leftOuter">
        <div class="leftInner">
            <div class="left">
                <div class="selectItem">热销</div>
                <div>折扣</div>
                <div>必点</div>
                <div>素菜</div>
                <div>饮料</div>
                <div>主食</div>
                <div>餐盒</div>
                <div>套餐</div>
            </div>
        </div>
    </div>
    <div class="rightOuter">
        <div class="rightInner">
            <div class="right">
                <ul>
                    <li>热销</li>
                    <li>热销</li>
                    <li>热销</li>
                </ul>
                <ul>
                    <li>折扣</li>
                    <li>折扣</li>
                    <li>折扣</li>
                </ul>
                <ul>
                    <li>必点</li>
                    <li>必点</li>
                </ul>
                <ul>
                    <li>素菜</li>
                    <li>素菜</li>
                    <li>素菜</li>
                    <li>素菜</li>
                    <li>素菜</li>
                    <li>素菜</li>
                </ul>
                <ul>
                    <li>饮料</li>
                    <li>饮料</li>
                    <li>饮料</li>
                </ul>
                <ul>
                    <li>主食</li>
                    <li>主食</li>
                    <li>主食</li>
                    <li>主食</li>
                    <li>主食</li>
                    <li>主食</li>
                    <li>主食</li>
                    <li>主食</li>
                </ul>
                <ul>
                    <li>餐盒1</li>
                    <li>餐盒2</li>
                    <li>餐盒3</li>
                    <li>餐盒4</li>
                    <li>餐盒5</li>
                    <li>餐盒6</li>
                    <li>餐盒7</li>
                </ul>
                <ul>
                    <li>套餐1</li>
                    <li>套餐2</li>
                    <li>套餐3</li>
                    <li>套餐4</li>
                    <li>套餐5</li>
                    <li>套餐6</li>
                    <li>套餐7</li>
                </ul>
            </div>
        </div>
    </div>
</div>
<script src="js/jquery-1.9.1.js"></script>
<script src="js/jquery-3.0.0.js"></script>
<script>
    $(function(){
        $(".rightInner").on("scroll",scrollEvent)
        $(".left>div").each(function (index) {
            $(this).click(function () {
                $(".rightInner").off("scroll",scrollEvent);
                setTop(index);
                $(this).addClass("selectItem").siblings().removeClass();
                var initTop = $(".rightInner").scrollTop();
                $(".rightInner").stop(true,true).animate({
                    "scrollTop":$(".right>ul").eq(index).position().top+initTop
                },function () {
                    //在scrollTop改变后还会调用一两次scroll对应的函数,三种添加函数方式都会调用(我猜是不可避免的)
                    $(".rightInner").on("scroll",scrollEvent)
                });
            })
        });
        function scrollEvent() {
                $(this).find("ul").each(function (index) {
                    if($(this).position().top<=0 && Math.abs($(this).position().top)<= $(this).height()){
                        //会进来两次,一次是点击的index对应的模块,一次是点击的index的上一个索引模块(最终会取点击的index对应的模块)
                        $(".left>div").eq(index).addClass("selectItem").siblings().removeClass();
                        setTop(index);
                    }
                })
        }
        function setTop(index) {
            console.log(index);
            if(index>=$(".left>div").length/2){
                $(".leftInner").stop().animate({
                    scrollTop:$(".leftInner").height()
                })
            }else{
                $(".leftInner").stop().animate({
                    scrollTop:0
                })
            }
        }
    })
</script>
</body>
</html>
4. 图片轮播
效果图

核心思想:

  1. 在准备展示第二张图片时(即nowIndex==图片总个数(包含最后一张图片)),先让整体的marginLeft变为0,并让nowIndex变为1(nowIndex用来控制marginLeft值),再根据nowIndexmarginLeft.此处注意:当展示最后一张图片时(与第一张相同),应让第一个圆圈变色。
  2. 在点击向左移动的按钮时,先nowIndex--,再判断nowIndex<0,若为true,则将marginLeft设置为最右边对齐。将nowIndex设置为图片总个数-2,然后再根据nowIndex求新的marginLeft值。
  3. 在点击向右移动的按钮时,先nowIndex++,若nowIndex为图片个数-1,其余操作不变,但底部第一个圆圈被选中。若nowIndex为图片个数时,将marginLeft设置为0,nowIndex设置为1。再根据nowIndex求新的marginLeft
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .all{
            position: relative;
            width: 500px;
            height: 300px;
            overflow: hidden;
            margin: auto;
        }
        .inner{
            width: 3000px;
            height: 300px;
            font-size: 0;
        }
        .inner>img{
            width: 500px;
            height: 300px;
            display: inline-block;
        }
        .circle{
            width: 150px;
            position: absolute;
            bottom: 5px;
            left:0;
            right:0;
            margin:auto;
            text-align:center;
        }
        .circle>span{
            display: inline-block;
            width: 15px;
            height:15px;
            border-radius:50%;
            border:1px solid white;
        }
        .choose{
            background: red;
        }
        .pos{
            position: absolute;
            top:0;
            bottom:0;
            margin:auto;
            height: 20px;
            width: 100%;
        }
        .pos>span{
            display: inline-block;
            width: 20px;
            height: 20px;
        }
        .left{
            position:absolute;
            left:0;
            background: white;
        }
        .right{
            position: absolute;
            right: 0;
            background: white;
        }
    </style>
</head>
<body>
<div class="all">
    <div class="inner">
        <img src="img/1.jpg">
        <img src="img/2.jpg">
        <img src="img/3.jpg">
        <img src="img/4.jpg">
        <img src="img/5.jpg">
        <img src="img/1.jpg">
    </div>
    <div class="circle">
        <span class="choose"></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div class="pos">
        <span class="left"></span>
        <span class="right"></span>
    </div>
</div>
</body>
<script src="js/jquery-3.0.0.js"></script>
<script>
$(function () {
    var nowIndex=0;
    var width = 500;
    var timer;
    function set(){
        $(".inner").stop().animate({
            "marginLeft":-nowIndex*width
        });
        $(".circle").find("span").eq(nowIndex).addClass("choose").siblings().removeClass();
    }
    function intervalTimer(){
            //在准备播放第二张图片时,让整体的marginLeft变为0,并让nowIndex为1
            nowIndex++;
            if(nowIndex==$(".inner").children().length){
                $(".inner").css({
                    marginLeft: 0
                });
                nowIndex=1;
            }
            set();//当nowIndex==$(".inner").children().length-1时,虽然找不到对应的圆圈,但是也不会报错
        if(nowIndex==$(".inner").children().length-1){
            $(".circle").find("span").eq(0).addClass("choose").siblings().removeClass();
        }
    }
    timer=setInterval(intervalTimer,1000);
    $(".all").on("mousemove mouseleave",function (e) {
        if(e.type=="mousemove"){
            clearInterval(timer)
        }else{
            timer=setInterval(intervalTimer,1000);
        }
    });
    $(".pos").children().click(function () {
        if($(this).html()=="左"){
            nowIndex--;
            if(nowIndex<0){
                nowIndex=$(".inner").children().length-2;
                $(".inner").css({
                    marginLeft:-(nowIndex+1)*width
                });
            }
            set();
        }else{
            nowIndex++;
            if(nowIndex==$(".inner").children().length){
                $(".inner").css({
                    marginLeft: 0
                });
                nowIndex=1;
            }
            if(nowIndex==$(".inner").children().length-1){
                //该判断可放到调用set前也可放到调用set后,由于无法找到nowIndex对应的圆圈,故在执行了set()方法后也不会改变选中的圆圈。
                $(".circle").find("span").eq(0).addClass("choose").siblings().removeClass();
            }
            set();
        }
    });
    $(".circle").children().each(function (index) {
        $(this).mouseenter(function () {
            nowIndex=index;
            set();
        })
    })
})
</script>
</html>

转载:https://blog.csdn.net/weixin_43314846/article/details/102466678
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场