切割轮播图,详解

今天写一个 切割轮播图,我这里是基于vue.js的。
首先,新建一个vue.js的项目,我这里就不多说了。因为我们用的是jQuery,这里我们第一步需要实现的是在vue项目中使用jQuery。(完整代码在最后

效果图如下:

jQuery 轮播动画_轮播图


1> 在控制台输入 cnpm i jquery --save或者 npm i jquery --save,添加相应的依赖。

jQuery 轮播动画_vue.js_02


2>这时我们就要修改配置文件了

  • webpack.base.conf.js 文件
    在文件头部添加 const webpack = require('webpack')
resolve: {
   extensions: ['.js', '.vue', '.json'],
   alias: {
     'vue$': 'vue/dist/vue.esm.js',
     '@': resolve('src'),
     // 添加 1
     'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery')
   }
 },
 // 添加 2
 plugins: [
   new webpack.optimize.CommonsChunkPlugin('common.js'),
   new webpack.ProvidePlugin({
     jQuery: 'jquery',
     $: 'jquery'
   })
 ],

3> 如果你的项目使用了严格模式,在 .eslintrc.js 文件添加jquery: true,如果没有启用严格模式,就不需要了。

env: {
   browser: true,
   // 添加
   jquery: true
 },

4>在 main.js 文件中 引用jQuery,就可以全局使用jQuery了,添加代码 import 'jquery'

我们现在使用一下jQuery,看看有效果没。

jQuery 轮播动画_jQuery 轮播动画_03


启动项目,F12 检查元素,成功。

jQuery 轮播动画_jQuery_04


现在我们构建切割轮播图的页面结构。

先看看要实现的效果

jQuery 轮播动画_轮播图_05


代码实现如下:

jQuery 轮播动画_jQuery_06

/* 设置宽度为400px,高度为300px */
.view {
  width: 400px;
  height: 300px;
}
.view li {
  width: 20%;/* 让每个li 继承父节点的 20% */
  height: 100%;
  list-style: none; /* 去掉li前面的小圆点样式 */
  float: left; /* 因为li是块级元素,要让每个li在一行显示才能拼成一张完整的图片 */
}
.view li span {
/* 让每个li下面的span继承父亲的宽高,并且使用绝对定位 */
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}

因为 span中使用了绝对定位,所以要在父亲节点(.view li),加上 position: relative;

这时,我们就可以加图片了,对新手来说,比较难理解的是每个图片的位置该怎么放。

.view li span:nth-child(1) {
  background: url("../assets/1.jpg") no-repeat;
}
.view li span:nth-child(2) {
  background: url("../assets/2.jpg") no-repeat;
}
.view li span:nth-child(3) {
  background: url("../assets/3.jpg") no-repeat;
}
.view li span:nth-child(4) {
  background: url("../assets/4.jpg") no-repeat;
}

上面这段代码写完,四张图片是重贴在一起的,先看看此时的效果图。

jQuery 轮播动画_jQuery 轮播动画_07


而且我们还发现,每个图片只显示了前面的20%,重复显示了5次。

我们先解决上面这个问题,先让图片显示完整再说。

为啥会出现上面的这种情况呢?
结合我们上面写好的代码,每个 li 的宽度,占了整个父节点(view)宽度的 20%,每个 span 的宽高继承了父节点(li)的100%,所以每个 span 的背景图片也只能显示前面的 20%。
怎么解决
分析一下,既然每个图片只显示前面的20%,那我们让第二个 li 中的 span 的背景图片 往前移动 20%的距离,让第三个 li 中的 span 的背景图片往前移动40%的距离,以此类推,后面的几个同理。这样刚刚可以拼出一张完整的图片。

.view li:nth-child(1) span {
    background-position: 0 0;
  }
  .view li:nth-child(2) span {
    background-position: -80px 0;
  }
  .view li:nth-child(3) span {
    background-position: -160px 0;
  }
  .view li:nth-child(4) span {
    background-position: -240px 0;
  }
  .view li:nth-child(5) span {
    background-position: -320px 0;
  }

这时,一张完整的图片就可以显示了。

jQuery 轮播动画_轮播图_08


下面我们要让每张图片放在该放的位置。这是想要的效果

jQuery 轮播动画_切割轮播图_09

.view li span:nth-child(1) {
  background: url("../assets/1.jpg") no-repeat;
  /* 第一张图往前走(Z轴正方向)图片高度的一半 */
  transform: translateZ(150px);
}
.view li span:nth-child(2) {
  background: url("../assets/2.jpg") no-repeat;
  /* 第二张图片往下走(Y轴正方向)150px,沿着x轴逆时针转90度 */
  transform: translateY(150px) rotateX(-90deg);
}
.view li span:nth-child(3) {
  background: url("../assets/3.jpg") no-repeat;
  /* 第三张图片往后走(Z轴负方向)150px,并且让图片反转180度,为的是,当这张图片翻到前面时,图片是正的 */
  transform: translateZ(-150px) rotateX(180deg);
}
.view li span:nth-child(4) {
  background: url("../assets/4.jpg") no-repeat;
  /* 第四张图往上走(Y轴负方向)150px,沿x轴顺时针转90度 */
  transform: translateY(-150px) rotateX(90deg);
}

为了 实现3D效果,我们要在 .view li 中 添加 transform-style: preserve-3d; 这句话的意思是让其子元素按照3d效果显示。

我们在 .view中添加 transform-style: preserve-3d; transform: rotate3d(1,1,0,-30deg); 打开页面我们可以看到这个效果。看完之后就可以删了。

jQuery 轮播动画_jQuery_10


图片比较花哨,有点看不清。。。不过还是可以看出来,是一个长方体。四张图片在前、下、后、上四个面,左右两边是空的。下面开始做按钮操作:

jQuery 轮播动画_vue.js_11


在 li 下面添加:

jQuery 轮播动画_切割轮播图_12

.pre,
  .next{
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 30px;
    line-height: 30px;
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
  }
  .pre {
    left: 0;
  }
  .next {
    right: 0;
  }

因为在 a 标签中加了 position: absolute; 所以要在父节点(view)中 添加 position: relative;

jQuery 轮播动画_切割轮播图_13


到此,样式全部写完了。

下面重头戏开始了。

$(function () {
      /* 点击左边按钮 */
      $('.pre').on('click', function () {
        /* 遍历每一个li,让其逆时针按X轴旋转90度 */
        $('li').each(function (key, value) { // key: 0 1 2 3 4
          $(this).css({
            'transform': 'rotateX(-90deg)'
          })
        })
      })
    })

这时点击左边的切换按钮,就可以实现切换图片了,但是发现,图片一闪而过,并没有有一个过渡效果。因为我们还没加啊。
这时我们给 li 添加过渡。在 .view li 中 添加 transition: all 0.6s 再去点击,就有过渡效果,但是还不是我们想要的。
我们要的是每个 li 一个接一个旋转90度。

添加代码:

jQuery 轮播动画_轮播图_14


让每个 li 延迟0…1s

这时点击就会有每个 看到了我们的 要的效果。但此时,只能点击一次,点击第二次就没有作用了。因为我们把,li 的旋转角度给写死了。把旋转角度改成动态的就OK了。修改代码如下:

jQuery 轮播动画_轮播图_15


这时左边的按钮就已经完成了。大功告成,。。。错了,不知道你们有没有发现一个bug,当你快速点击时,轮播图就出现紊乱,我们想要的效果是,当前这次轮播图还没有播放完成,点击按钮不生效。这时,我们要给它加个节流阀。也就是一个开关。

jQuery 轮播动画_jQuery_16


如果 flag 为 true,则进入到 if 条件语句中,执行轮播图播放效果,并把 flag 设置为 false 。那什么时候让 flag 又变回 true 呢??我们给个定时器,因为 每个 li 我们给它延时了 100ms,所以我们给定时器的时间设置为 500ms,只有 500ms过了之后,点击才会有效。

这回,你再去点击,就正常了。那么,右边按钮,和左边同理,只需要把 index-- 改成 index++。

最后,附上完整代码。

<template>
  <div class="view">
    <li>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </li>
    <li>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </li>
    <li>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </li>
    <li>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </li>
    <li>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </li>
    <a class="pre">《 </a>
    <a class="next"> 》</a>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {}
  },
  mounted () {
    $(function () {
      let index = 0
      /* 设置节流阀 */
      let flag = true
      /* 点击左边按钮 */
      $('.pre').on('click', function () {
        if (flag) {
          flag = false
          index--
          /* 遍历每一个li,让其逆时针按X轴旋转90度 */
          $('li').each(function (key, value) { // key: 0 1 2 3 4
            $(this).css({
              'transform': 'rotateX(' + (index * 90) + 'deg)',
              'transition-delay': key * 0.1 + 's'
            })
          })
          setTimeout(function () {
            flag = true
          }, 500)
        }
      })
      /* 点击右边按钮 */
      $('.next').on('click', function () {
        if (flag) {
          flag = false
          index++
          /* 遍历每一个li,让其顺时针按X轴旋转90度 */
          $('li').each(function (key, value) { // key: 0 1 2 3 4
            $(this).css({
              'transform': 'rotateX(' + (index * 90) + 'deg)',
              'transition-delay': key * 0.1 + 's'
            })
          })
          setTimeout(function () {
            flag = true
          }, 500)
        }
      })
    })
  }
}
</script>

<style scoped>
  /* 设置宽度为400px,高度为300px */
.view {
  margin: 100px auto;
  width: 400px;
  height: 280px;
  /*transform-style: preserve-3d;*/
  /*transform: rotate3d(1,1,0,-30deg);*/
  position: relative;
}
  /* 让每个li 继承父节点的 20% */
.view li {
  width: 20%;
  height: 100%;
  list-style: none;
  float: left;
  position: relative;
  transform-style: preserve-3d;
  transition: all 0.6s;
}
.view li span {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
.view li span:nth-child(1) {
  background: url("../assets/1.jpg") no-repeat;
  transform: translateZ(140px);
}
.view li span:nth-child(2) {
  background: url("../assets/2.jpg") no-repeat;
  transform: translateY(140px) rotateX(-90deg);
}
.view li span:nth-child(3) {
  background: url("../assets/3.jpg") no-repeat;
  transform: translateZ(-140px) rotateX(180deg);
}
.view li span:nth-child(4) {
  background: url("../assets/4.jpg") no-repeat;
  transform: translateY(-140px) rotateX(90deg);
}
  .view li:nth-child(1) span {
    background-position: 0 0;
  }
  .view li:nth-child(2) span {
    background-position: -80px 0;
  }
  .view li:nth-child(3) span {
    background-position: -160px 0;
  }
  .view li:nth-child(4) span {
    background-position: -240px 0;
  }
  .view li:nth-child(5) span {
    background-position: -320px 0;
  }
  .pre,
  .next{
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 30px;
    line-height: 30px;
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
  }
  .pre {
    left: 0;
  }
  .next {
    right: 0;
  }
</style>

最最后,给一个项目链接,美滋滋!

切割轮播图