js实现轮播效果几种方式

轮播呢,也是各种网站上常见的一种展示效果,这里我来写一写实现轮播的一些简单方法。
//不知道为什么系统吃了代码里面的img标签,大佬们有解决方式么?

1.原生js轮播

原生的轮播效果,这里实现的原理:有个一个放置图片列表的块级元素,放置所有的图片,我这里使用的是横向的列表;他的父元素为一个展示块,宽高为一张图片的宽高,利用overflow:hidden属性,每次只展示一张图片,隐藏其他图片,再用js控制图片列表定时或者其他方式左移右移即可实现简单的轮播了。下图图片处为overflow:hidden的父元素,1500*200为图片列表。

image.png

为了让轮播更流畅,在最后一张图片后面插入第一张图片。

image.png
.box{
  width:300px;
  height:200px;
  margin:100px auto;
  overflow: hidden;
}
.img-g{
  width:1500px;
  height:200px;
}
.img-g img{
  width:300px;
  height:200px;
}

将图片列表position设为relative,就可以利用偏移来移动图片了,为了方便,这里将left属性内联到img-g里。
如left为-100px时

image.png

然后用js获得图片列表的style.left,使用定时器控制他的偏移量,就可以实现简单的轮播了。

let p=document.getElementsByClassName('img-g')[0];
let timer=setInterval(move,2000);
function move(){
  if(parseInt(p.style.left)>-1200){
    p.style.left=parseInt(p.style.left)-300+'px'
    console.log(p.style.left)
  }else{
    p.style.left='-300px'
  }
}

不过光有图片的移动还不够,为了让图片切换更自然一点,可以加入css3对left的过渡。
不过最后一张切换到第一张时的过渡是相反的,因此还是使用js控制过渡属性。
从最后一张图片到第一张图片的过渡稍微麻烦一些,我最后使用定时器,让图片滑到最后一张,等过渡动画完成之后,取消过渡动画,切换到第一张之后再开启动画。这部分代码如下

image.png
let p=document.getElementsByClassName('img-g')[0];
let timer=setInterval(move,2000);
function move(){
  if(parseInt(p.style.left)>-1200){
    p.style.left=parseInt(p.style.left)-300+'px'
    p.style.transition='left 1s';
    if(parseInt(p.style.left)<=-1200){
        console.log('t')
        setTimeout(function(){
          p.style.left='0px'
          p.style.transition='left 0s';
        },1000)
    }
  }else{
    p.style.left='0px'
    p.style.transition='left 0s';
  }
}

到这里,轮播的功能已经实现了,还可以为它加上几个小圆点,控制轮播现在正在播放的图。
小圆点html

<div class='button-g'>
      <span data-index='0' ></span>
      <span data-index='1'></span>
      <span data-index='2'></span>
      <span data-index='3'></span>
    </div>
.button-g{
  position:relative;
  top:-20px;
  text-align:center;
}
.button-g span{
  display:inline-block;
  position:relative;
  z-index:10;
  width:10px;
  height:10px;
  margin:0 5px;
  border-radius:100%;
}

小圆点被点击时,图片滑动至小圆点对应的图片,并且图片滑动时小圆点也跟着变化,我在每个小圆点属性中加入了data-属性,该属性可被js获取。
为小圆点加入事件,被点击时滑动对应的偏移量。

for(let i=0;i<button.length;i++){
  button[i].onclick=function(){
    p.style.left=-300*this.getAttribute('data-index')+'px'
    tog(this.getAttribute('data-index'))
  }
}

function tog(index){
  if(index>3){tog(0);return;}
  for(let i=0;i<button.length;i++){
    button[i].style.backgroundColor='#eee'
  }
  button[index].style.backgroundColor='rgb(215, 81, 15)';
}

常见的轮播还有一种效果,就是鼠标只在图片上的时候,暂停轮播;鼠标离开时继续轮播。
以这种思路,很容易实现想要的效果。

p.onmouseover=function(){
  clearInterval(window.timer)
}
p.onmouseout=function(){
  window.timer=setInterval(move,3000);
}

实际效果可以看下面链接:
https://zkhchris.github.io/FE_basic/hc/Carousel/carousel_pure_js.html

2.css3轮播

这里使用css3动画实现了一个渐显渐隐的效果,使用absolute定位,让图片列表中的图片叠加在一起,通过动画控制z-index和透明度实现渐显渐隐。
absolute元素相对于第一个定位不是static的父元素定位,因此该元素都叠加在一个显示块中。

image.png

然后使用css3动画按时间循环改变他们的透明度和z-index,即可完成简单的轮播效果。
这里每张图片占用的动画时间为4s,总动画时间即为16s。淡入淡出都是1s,占用总时间约为6%,在最顶层的时间为3s,占用总时间18.7%;按此比例设置keyframe

.imglist img{
  width:300px;
  height:200px;
  position:absolute;
  animation: show 16s infinite;
}
@keyframes show{
  0%{
    opacity:0;
    z-index:2;
  }
  6%,25%{
    opacity:1;
    z-index: 1;
  }
  31%,100%{
    opacity:0;
    z-index:0;
  }
}

这时图片都可以按时间循环出现,不过他们现在是同时出现,同时消失的,为图片加上延时即可完成效果。

#img2{
    animation-delay: 0s;
}
#img2{
    animation-delay: 4s;
}
#img3{
    animation-delay: 8s;
}
#img4{
    animation-delay: 12s;
}

css3轮播可实现轮播效果,但是没有办法控制现在要播哪张图片,因此尽量使用js控制轮播效果。
https://zkhchris.github.io/FE_basic/hc/Carousel/css3carousel.html

3.vue轮播

使用vue轮播,可以使用列表渲染动态加入想轮播的图片,使用vue自带的列表过渡,可实现轮播效果。
这里使用非无定位轮播框父元素加上子元素为absolute图片,配合v-show实现轮播效果。
列表渲染图片

<template>
    <div id='swiper_img_box'>
    <ul class='swiper_img_ul'>
image.png
    </ul>
        <ul class='buttonG'>
        <span v-for='(img,index) in imgs' :key='index' ></span>
        </ul>
    </div>
</template>

<style>
  .swiper_img_ul{
    height:300px;
  }
  .swiper_img_ul img{
    position:absolute;
  }
  #swiper_img_box{
    position:relative;
    width:300px;
    height:300px;
    overflow:hidden;
  }
  .buttonG{
    position:absolute;
    bottom:0;
  }
  .circle{
    display:inline-block;
    width:15px;
    height:15px;
    border-radius:100%;
    margin-left:10px;
  }
</style>

使用v-show来控制图片是否显示,在使用定时器来定时修改当前显示的图片,定时器挂在了mounted上。

image.png
  mounted:function(){
    this.timer=setInterval(this.changeIndex,2000)
    },
  methods:{
    changeIndex(){
      if(this.showIndex>=this.imgs.length-1){
        this.showIndex=0
      }else{
        this.showIndex++
      }
    }

  data () {
    return {
      imgs:[
            {
            src:'../../dist/7.gif',
            alt:'1'
            },{
            src:'../../dist/home_06.gif',
            alt:'2'
            },{
            src:'../../dist/home_08.gif',
            alt:'3'
            },{
            src:'../../dist/home_12.gif',
            alt:'4'
            }
          ],
          showIndex:0
    }
    },

这样,通过定时器,可以控制图片的轮播了,但是没有过渡效果,轮播很突兀,加上过渡效果就好了。

<transition-group name='image' tag="ul" class='swiper_img_ul'>

  .image-enter-active {
            transform: translateX(0);
            transition: all 1s ease;
        }

  .image-leave-active {
            transform: translateX(-100%);
            transition: all 1s ease;
        }

  .image-enter {
            transform: translateX(100%)
        }

  .image-leave {
            transform: translateX(0)
                }

在加上常见的鼠标mouseover暂停,mouseout继续,点击按钮轮播至所点击按钮对应的图片。

<transition-group name='image' tag="ul" class='swiper_img_ul'>
        <img  ...... @mouseover='stop' @mouseout='start'>
    </transition-group>
        <ul class='buttonG'>
        <span ...... @click='goto(index)'></span>
       </ul>

  methods:{
    changeIndex(){
      if(this.showIndex>=this.imgs.length-1){
        this.showIndex=0
      }else{
        this.showIndex++
      }
    },
    stop(){
      console.log('1')
      clearInterval(this.timer)
    },
    start(){
      this.timer=setInterval(this.changeIndex,2000)
    },
    goto(i){
      this.showIndex=i
      this.stop()
      this.start()
    }
  }

这时轮播效果就实现的差不多了,不过这个vue轮播我是写成了单文件组件的形式,无法预览,就在下方贴上这个代码。

谢谢大家阅读,希望大佬们多多指点。

swiper.vue

<template>
    <div id='swiper_img_box'>
image.png
        <ul class='buttonG'>
        <span v-for='(img,index) in imgs' :key='index' :class="[index==showIndex ? 'color' : 'white', 'circle']" @click='goto(index)'></span>
        </ul>
    </div>
</template>
<script>
export default{
  name:'swiper',
  data () {
    return {
      imgs:[
            {
            src:'../../dist/7.gif',
            alt:'1'
            },{
            src:'../../dist/home_06.gif',
            alt:'2'
            },{
            src:'../../dist/home_08.gif',
            alt:'3'
            },{
            src:'../../dist/home_12.gif',
            alt:'4'
            }
          ],
          showIndex:0
    }
    },
  mounted:function(){
    this.timer=setInterval(this.changeIndex,2000)
    }
,
  methods:{
    changeIndex(){
      if(this.showIndex>=this.imgs.length-1){
        this.showIndex=0
      }else{
        this.showIndex++
      }
    },
    stop(){
      clearInterval(this.timer)
    },
    start(){
      this.timer=setInterval(this.changeIndex,2000)
    },
    goto(i){
      this.showIndex=i
      this.stop()
      this.start()
    }
  }
}
</script>
<style>
  .swiper_img_ul{
    height:300px;
  }
  .swiper_img_ul img{
    position:absolute;
  }
  #swiper_img_box{
    position:relative;
    width:300px;
    height:300px;
    overflow:hidden;
  }
  .buttonG{
    position:absolute;
    bottom:0;
  }
  .circle{
    display:inline-block;
    width:15px;
    height:15px;
    border-radius:100%;
    margin-left:10px;
  }
  .white{
    background-color:#fff;
  }
  .color{
    background-color:#f00;
  }
  .image-enter-active {
            transform: translateX(0);
            transition: all 1s ease;
        }

  .image-leave-active {
            transform: translateX(-100%);
            transition: all 1s ease;
        }

  .image-enter {
            transform: translateX(100%)
        }

  .image-leave {
            transform: translateX(0)
                }
</style>

谢谢大家阅读,希望大佬们多多指点!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容