美文网首页让前端飞Web前端之路
jQuery实现自动切换动画

jQuery实现自动切换动画

作者: 超人鸭 | 来源:发表于2020-03-23 14:49 被阅读0次
test2 (1).gif
image.png

gif压缩得太厉害了,可能看不清或者加载不出,大家可以到我司官网看看效果,点击这里进入官网

不知道这种效果是不是你们想要的效果,这是超人鸭开发公司官网遇到的一个需求,结合上面的动图梳理一下需求:

  1. 一进页面动画会自动执行,且是循环执行。
  2. 分为三项,中间以类似进度条的元素连接,主要动画也是这个进度条。
  3. 上面第几个图标激活时,下面显示对应的内容。
  4. 点击上面的图标时,下面内容做对应切换,同时停止动画不再执行,进度条也不显示。

这就是大概的需求,那如何实现呢,我进行了简单的分析:
上面的进度条动画用到jquery中的animate方法,一开始将进度条的宽度设置为零,在一定的时间内将宽度变成100%,激活对应的图标,同时在动画开始时要将其他的进度条宽度设置为零。下面内容的切换根据上面的激活的图标是第几个进行显示,问题的关键就是如何知道激活的图标是第几个,也就是index,在激活的图标改变时下面的内容也要跟着改变,所以就要监听这个index的变化,在它变化时做出相应的操作,那在js中监听一个变量的变化我用到的是Object.defineProperty(),用它来改写对象属性的get和set,不了解这个api的朋友可以翻阅一下,不难理解。

下面我就一步一步现实这个自动切换的动画效果,首先是上面控制的图标与进度条html和css,这个dom结构看清楚可以提升文章观看体验:

html:
    <div class="control-box">
        <div class="process-box">
            <div class="process-item active"></div>
            <!-- process-line就代表进度条,里面有两个子元素,代表初始的线和进度条 -->
            <div class="process-line">
                <div class="active-line"></div>
                <div class="dot-line"></div>
            </div>
            <div class="process-item"></div>
            <div class="process-line">
                <div class="active-line"></div>
                <div class="dot-line"></div>
            </div>
            <div class="process-item"></div>
        </div>
    </div>
css:
    <style>
        .control-box{
            margin: 0 auto;
            width: 50%;
            display: flex;
            align-items: center;
        }
        .process-box{
            flex: 1;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .process-item{
            width: 30px;
            height: 30px;
            border-radius: 50%;
            border: 1px solid gray;
        }
        .process-item.active{
            background: blue;
        }
        .process-line{
            width: 100px;
            position: relative;
        }
        .dot-line{
            position: absolute;
            width: 100%;
            height: 1px;
            background: red;
        }
        .active-line{
            position: absolute;
            background: blue;
            width: 0px;
            height: 3px;
            z-index: 2;
            top: -1px;
        }
    </style>

效果:


image.png

接下来是实现动画,上面说到,要去监听一个变量的变化,代表上面图标的index,当它改变时去做相应的操作,所以先来监听一个变量:

var indexObj = {}
var temp = null
Object.defineProperty(indexObj, 'index', {
  get: function() {
    return temp
  },
  set: function(value) {
    temp = value
    // 执行某些操作
    setActive(temp)
  }
});

其中temp是一个中间变量,因为我们要取这个index,也就是执行get方法,如果在get里面直接return这个属性,那return 的时候相当会再执行一次get,就会陷入死循环,最后报错:

var indexObj = {}
var temp = null
Object.defineProperty(indexObj, 'index', {
  get: function() {
    return this.index
  },
  set: function(value) {
    temp = value
    // 执行某些操作
    setActive(temp)
  }
});
indexObj.index = 0
console.log(indexObj.index)
image.png

所以使用要使用get的时候需要一个临时变量,return这个临时变量temp。到这里我们就能监听一个变量的变化了,它代表着当前激活的是第几个图标,也就是index,当它改变时我们去执行setActive这个方法,并把index传进去:

function setActive(val) {
  //  $(".process-item")就是代表上面的图标(圆点)
  $(".process-item").removeClass('active')
  // eq里面写变量需要像这样写,不然会被识别成字符串
  $(".process-item:eq("+(val)+")").addClass('active')
}

接下来就是进度条的动画了,当进度条动画执行完后,index+1,图标的激活样式就会自动改变,因为我们已经监听了它的变化,这里用到jQuery的animate方法,而且用到了它的回调函数,用法是这样:

$(selector).animate(styles,speed,easing,callback)
第三个参数我忽略掉了,看看例子:
$('div').animate({width:'100%'},1000,function(){alert()})
表示选中div元素在一秒内宽度变成100%,完成后alert()

初步实现进度条动画:

function setLineWidth(){
  // 动画开始前将其他进度条清空
  $(".active-line").not(".active-line:eq("+(indexObj.index)+")").css("width",'0px')
  $(".active-line:eq("+(indexObj.index)+")").animate({width:'100%'},1000,function() {
    indexObj.index += 1
    setLineWidth() // 再次执行
  })
}
setLineWidth()

这样是能执行一遍动画,但是以我的图片例子,进度条只有两个,所以操作进度条的index最大只能是1,而上面的图标(圆点)包括内容有三个,所以操作他们的index最大只能是2,配合动画循环的需求,我改写一下监听index的方法:

Object.defineProperty(indexObj, 'index', {
  get: function() {
    return temp
  },
  set: function(value) {
    if(value===3){
      temp = 0
    }
    temp = value
    // 执行某些操作
    setActive(temp)
  }
});

加个判断让index可以在0到2之间循环,但是操作进度条的index最大只能是1,当index=2的时候,应该不操作进度条,改写一下上面的setLineWidth方法:

function setLineWidth(){
  // 动画开始前将其他进度条清空
  $(".active-line").not(".active-line:eq("+(indexObj.index)+")").css("width",'0px')
  if(indexObj.index < 2) {
      $(".active-line:eq("+(indexObj.index)+")").animate({width:'100%'},1000,function() {
        indexObj.index += 1
        setLineWidth() // 再次执行
      })
  } else { // index等于2的情况
    setTimeout(function() {
      indexObj.index += 1 // 当index=3的时候会自动变成0
      setLineWidth()
    },1000) // 保持一样的时间
  }
}
setLineWidth()

效果:


1.gif

接下来实现点击上面的图标时,内容对应切换,并停止动画:
首先是对应的激活样式切换,这个直接在点击事件里面改变index就可以,然后要停止动画,并且清空进度条,我们先定义一个全局变量,然后在这个点击事件里面改变,并改写上面的setLineWidth方法:

var isClick = false // 表示是否点击
$(".process-item").click(function() {
  $(".active-line").css("display", "none") // 隐藏进度条
  isClick = true // 表示点击
  indexObj.index = $(".process-item").index(this) // 改变index
})

function setLineWidth() {
  if(isClick) {
    return
  }
  $(".active-line").not(".active-line:eq("+(indexObj.index)+")").css("width",'0px')
    if(indexObj.index < 2) {
      $(".active-line:eq("+(indexObj.index)+")").animate({width:'100%'},1000,function() {
        if(isClick) {
          return
        }
        indexObj.index += 1
        setLineWidth()
      })
    } else {
      setTimeout(function() {
        if(isClick) {
          return
        }
        indexObj.index += 1
        setLineWidth()
      }, 1000)
    }
}

之所以在里面动画执行完也加了判断是因为动画的执行时间为一秒,那当你点击的时候它可能在执行的过程中,那index还是会改变,这样是不行的,所以每一个步骤都要加上判断,看看现在的效果:


1.gif

到这里,上面的图标控制和进度条动画已经实现了,下面的内容跟着切换其实也是一样,用的还是写好的index逻辑,切换的动画直接用css的过渡就可以实现,下面我简单演示一下,加一下html与css,都是在上面的代码后面直接加上:

html:
<div class="content">
  <div class="content-item active">1</div>
  <div class="content-item">2</div>
  <div class="content-item">3</div>
</div>

css:
.content-item{
    width: 100%;
    height: 200px;
    position: absolute;
    right: -400px;
    font-size: 30px;
    opacity: 0;
    transition: all 0.8s;
}
.content-item:nth-of-type(1){
    background: yellow;
}
.content-item:nth-of-type(2){
    background: blue;
}
.content-item:nth-of-type(3){
    background: red;
}
.content-item.active{
    opacity: 1;
    right: 0;
}

所以只需要根据index切换active这个class就可以了,在setActive方法里面添加切换的代码:

function setActive(val) {
  //  $(".process-item")就是代表上面的图标(圆点)
  $(".process-item").removeClass('active')
  // eq里面写变量需要像这样写,不然会被识别成字符串
  $(".process-item:eq("+(val)+")").addClass('active')

  $(".content-item").removeClass('active')
  $(".content-item:eq("+(val)+")").addClass('active')
}

效果:


1.gif

到这里完整的效果已经实现了,下面是完整的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <style>
        .control-box{
            margin: 0 auto;
            width: 50%;
            display: flex;
            align-items: center;
        }
        .process-box{
            flex: 1;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .process-item{
            width: 30px;
            height: 30px;
            border-radius: 50%;
            border: 1px solid gray;
        }
        .process-item.active{
            background: blue;
        }
        .process-line{
            width: 100px;
            position: relative;
        }
        .dot-line{
            position: absolute;
            width: 100%;
            height: 1px;
            background: red;
        }
        .active-line{
            position: absolute;
            background: blue;
            width: 0px;
            height: 3px;
            z-index: 2;
            top: -1px;
        }
        .content{
            position: relative;
            height: 200px;
            margin: 0 auto;
            width: 50%;
            margin-top: 20px;
            overflow: hidden;
        }
        .content-item{
            width: 100%;
            height: 200px;
            position: absolute;
            right: -400px;
            font-size: 30px;
            opacity: 0;
            transition: all 0.8s;
        }
        .content-item:nth-of-type(1){
            background: yellow;
        }
        .content-item:nth-of-type(2){
            background: blue;
        }
        .content-item:nth-of-type(3){
            background: red;
        }
        .content-item.active{
            opacity: 1;
            right: 0;
        }
    </style>
</head>
<body>
    <div class="control-box">
        <div class="process-box">
            <div class="process-item active"></div>
            <div class="process-line">
                <div class="active-line"></div>
                <div class="dot-line"></div>
            </div>
            <div class="process-item"></div>
            <div class="process-line">
                <div class="active-line"></div>
                <div class="dot-line"></div>
            </div>
            <div class="process-item"></div>
        </div>
    </div>
    <div class="content">
        <div class="content-item active">1</div>
        <div class="content-item">2</div>
        <div class="content-item">3</div>
    </div>

    <script>
        $(document).ready(function() {
            var indexObj = {}
            var temp = null
            var isClick = false
            Object.defineProperty(indexObj, 'index', {
                get: function() {
                    return temp
                },
                set: function(value) {
                    if(value === 3) {
                        temp = 0
                    } else if(value === -1){
                        temp = 2
                    } else {
                        temp = value
                    }
                    setActive(temp)
                }
            });
            indexObj.index = 0

            setLineWidth()
            function setLineWidth() {
                if(isClick) {
                    return
                }
                $(".active-line").not(".active-line:eq("+(indexObj.index)+")").css("width",'0px')
                if(indexObj.index < 2) {
                    $(".active-line:eq("+(indexObj.index)+")").animate({width:'100%'},1000,function() {
                        if(isClick) {
                            return
                        }
                        indexObj.index += 1
                        setLineWidth()
                    })
                } else {
                    setTimeout(function() {
                        if(isClick) {
                            return
                        }
                        indexObj.index += 1
                        setLineWidth()
                    }, 1000)
                }
            }

            $(".process-item").click(function() {
                $(".active-line").css("display", "none")
                isClick = true
                indexObj.index = $(".process-item").index(this)
            })
            
            function setActive(val) {
                $(".process-item").removeClass('active')
                $(".process-item:eq("+(val)+")").addClass('active')

                $(".content-item").removeClass('active')
                $(".content-item:eq("+(val)+")").addClass('active')
            }
        })
    </script>
</body>
</html>

虽然现在jQuery用得越来越少(我也不愿意写),但是不得不说在做公司官网这种以展示为主的项目,用jQuery还是首选,所以熟悉一下也不吃亏是吧,嘻嘻。

作者微信:Aqing1906
欢迎指教哦

相关文章

  • jQuery实现自动切换动画

    gif压缩得太厉害了,可能看不清或者加载不出,大家可以到我司官网看看效果,点击这里进入官网 不知道这种效果是不是你...

  • jquery3d轮播插件

    jquery 旋转木马 banner切换 github源码下载地址 实现原理 利用 css3 来实现动画当切换下...

  • jQuery实现tab切换

    jQuery实现tab切换

  • 用 jQuery 做个轮播

    初次体验jQuery 之后,体验一下jQuery强大之处,做一个简单的轮播,实现图片切换。 点击按钮切换轮播 页面...

  • 翻译:实现不包含jQuery的动画

    标题 中文:实现不包含jQuery的动画原文:Animating Without jQuery 重点句 CSS a...

  • diagnosite网站

    网站整体介绍 网站属于整屏切换网站 使用工具 jquery选择元素,绑定事件 TweenMax做动画,管理动画状态...

  • web高性能动画及渲染原理

    如何实现动画? jQuery animation:setTimeout,top/left animatin,tra...

  • [JavaScript] (Day-27) - jQuery

    使用jQuery实现动画,代码已经简单得不能再简化了:只需要一行代码! jQuery内置的几种动画样式: show...

  • jQuery动画队列

    队列实现是jQuery非常棒的一个拓展,使用动画队列可以使动画更容易实现。 .animate( propertie...

  • jQuery

    1 利用jQuery实现浮层弹出框作业 2 利用jquery切换元素样式的颜色($('#d1').toggleCl...

网友评论

    本文标题:jQuery实现自动切换动画

    本文链接:https://www.haomeiwen.com/subject/ghuiyhtx.html