全屏滚动之Vue2+Swiper+Animate

1,255 阅读2分钟

全屏滚动之Vue2+Swiper+Animate

需求

在vue2项目中,编写一个全屏滚动首页。切换时,页面中的元素需要有动画效果。

具体实现

一、 Swiper部分

1. 安装Swiper相关依赖

  • 这里我使用的Swiper5版本。
npm install swiper@5.4.5
npm install vue-awesome-swiper@4.1.1

2. 全局使用Swiper

// main.js
import VueAwesomeSwiper from 'vue-awesome-swiper'
import 'swiper/css/swiper.css'

// 使用swiper
Vue.use(VueAwesomeSwiper)

3. 初始化Swiper

  • html 部分
<!-- 主体为swiper标签 -->
<!--属性 :options 绑定的是data中设置的swiper配置项-->
<!--属性 ref 用于获取该dom元素,在计算属性computed中将被调用-->
<!--属性 id 为swiper最外层容器设置css样式-->
<swiper :options="swiperOption" ref="mySwiper" id="mySwiper">
  <!--必须的组件-->
  <!--每页幻灯片使用swiper-slide标签-->
  <!--幻灯片组件生成的标签自带.swiper-slide的类名,但单类名选择器设置的部分css(如宽高)将被覆盖-->
  <swiper-slide class="swiper_slide_item"><SwiperItem1 /></swiper-slide>
  <swiper-slide class="swiper_slide_item"><SwiperItem2 /></swiper-slide>
  <swiper-slide class="swiper_slide_item"><SwiperItem3 /></swiper-slide>

  <!-- 可选的控件 -->
  <!--分页器-->
  <div class="swiper-pagination" slot="pagination"></div>
  
  <!-- 左右箭头 --> 
  <div class="swiper-button-prev" slot="button-prev"></div> 
  <div class="swiper-button-next" slot="button-next"></div>
</swiper>
  • js 部分
    Swiper配置,写在swiperOption中。这里只写了需求相关配置,其他配置请参考官网文档。
// swiper.vue
<script>
export default {
    data() {
        return {
            activeIndex: 0, // 当前页index

            // swiper 配置
            swiperOption: {
                direction: 'vertical', // swiper 方向
                mousewheel: true,

                // 分页器
                pagination: {
                    el: '.swiper-pagination', //分页器的类名
                    clickable: true // 点击分页器跳切换到相应的幻灯片
                },

                on: {
                    // 翻页
                    slideChange: () => {
                        // 记录当前页index
                        this.activeIndex = this.$refs.mySwiper.$swiper.activeIndex
                    },
                }
            }
        }
    },
}
</script>

4. 全屏滚动效果图

af56b4de-78ba-41c0-8fb7-5682d402a51a.gif

二、 Animate部分

1. 安装animate.css依赖

npm install animate.css@3

2. 全局使用animate.css样式

// main.js
import animated from 'animate.css'

// 使用animate.css
Vue.use(animated)

3. 使用animate.js方法

  • 因为swiper官网提供的js文件不是export方式导出的,所以我们引入时会报错,我在各大网站上找到里一个更改以后的js文件。
  • 创建一个animate.js文件,将以下代码复制到创建的js文件里.
// utils/animate.js
export function swiperAnimateCache() {
  const allBoxes = window.document.documentElement.querySelectorAll('.ani')
  for (var i = 0; i < allBoxes.length; i++) {
    allBoxes[i].attributes['style']
      ? allBoxes[i].setAttribute(
          'swiper-animate-style-cache',
          allBoxes[i].attributes['style'].value
        )
      : allBoxes[i].setAttribute('swiper-animate-style-cache', ' ')
    allBoxes[i].style.visibility = 'hidden'
  }
}

export function swiperAnimate(a) {
  clearSwiperAnimate()
  var b = a.slides[a.activeIndex].querySelectorAll('.ani')
  for (var i = 0; i < b.length; i++) {
    b[i].style.visibility = 'visible'
    const effect = b[i].attributes['swiper-animate-effect']
      ? b[i].attributes['swiper-animate-effect'].value
      : ''
    b[i].className = b[i].className + ' ' + effect + ' ' + 'animated'
    const duration = b[i].attributes['swiper-animate-duration']
      ? b[i].attributes['swiper-animate-duration'].value
      : ''
    // duration && style
    const delay = b[i].attributes['swiper-animate-delay']
      ? b[i].attributes['swiper-animate-delay'].value
      : ''
    const style =
      b[i].attributes['style'].value +
      'animation-duration:' +
      duration +
      ';-webkit-animation-duration:' +
      duration +
      ';' +
      'animation-delay:' +
      delay +
      ';-webkit-animation-delay:' +
      delay +
      ';'
    // delay && (style = style )
    b[i].setAttribute('style', style)
  }
}

export function clearSwiperAnimate() {
  var allBoxes = window.document.documentElement.querySelectorAll('.ani')
  for (var i = 0; i < allBoxes.length; i++) {
    allBoxes[i].attributes['swiper-animate-style-cache'] &&
      allBoxes[i].setAttribute(
        'style',
        allBoxes[i].attributes['swiper-animate-style-cache'].value
      )
    allBoxes[i].style.visibility = 'hidden'
    allBoxes[i].className = allBoxes[i].className.replace('animated', ' ')
    const effectValue = allBoxes[i].attributes['swiper-animate-effect'].value
    /* eslint-disable-next-line */
    allBoxes[i].attributes['swiper-animate-effect'] &&
      (effectValue,
      (allBoxes[i].className = allBoxes[i].className.replace(effectValue, ' ')))
  }
}

  • 在动画相关页面引入
<script>
import { swiperAnimateCache, swiperAnimate } from '@/utils/animate'

export default {
data() {
    return {
      // swiper 配置
      swiperOption: {
        direction: 'vertical', // swiper 方向
        mousewheel: true,

        // 分页器
        pagination: {
          el: '.swiper-pagination', //分页器的类名
          clickable: true // 点击分页器跳切换到相应的幻灯片
        },

        on: {
          // 初始化
          init: () => {
            this.$nextTick(() => {
              const mySwiper = this.$refs.mySwiper.$swiper

              //隐藏动画元素
              swiperAnimateCache(mySwiper)

              //初始化完成开始动画
              swiperAnimate(mySwiper)
            })
          },

          slideChangeTransitionStart: () => {
            //每个slide切换结束时也运行当前slide动画
            swiperAnimate(this.$refs.mySwiper.$swiper)
          }
        }
      }
    }
  },
}

4. 动画设置

  • 在需要展示动画的DOM元素上增加以下内容。
  • class='ani'是必须要加的。
<div class="swiper1">
    <!-- 增加类名ani -->
    <!-- swiper-animate-effect 切换效果,例如fadeInUp -->
    <!-- swiper-animate-duration 动画持续时间(选填),例如.5s -->
    <!-- swiper-animate-delay 动画延迟时间(选填),例如1s -->
    <h1
      class="ani"
      swiper-animate-effect="bounceInLeft"
      swiper-animate-duration="1s"
      swiper-animate-delay="0.3s"
    >
      page 1
    </h1>
</div>

5. 最终效果

772a3a81-3f50-4e59-8745-f2fc804417e5.gif

vue 完整代码

// swiper.vue 完整代码
<script>
import { swiperAnimateCache, swiperAnimate } from '@/utils/animate'

export default {
    data() {
        return {
            activeIndex: 0, // 当前页index

            // swiper 配置
            swiperOption: {
                direction: 'vertical', // swiper 方向
                mousewheel: true,

                // 分页器
                pagination: {
                    el: '.swiper-pagination', //分页器的类名
                    clickable: true // 点击分页器跳切换到相应的幻灯片
                },

                on: {
                    // 初始化
                    init: () => {
                        // Swiper初始化,需要放在$nextTick()中,否则可能会获取不到元素
                        this.$nextTick(() => {
                            const mySwiper = this.$refs.mySwiper.$swiper

                            //隐藏动画元素
                            swiperAnimateCache(mySwiper)

                            //初始化完成开始动画
                            swiperAnimate(mySwiper)
                        })
                    },

                    // 翻页
                    slideChange: () => {
                        // 记录当前页index
                        this.activeIndex = this.$refs.mySwiper.$swiper.activeIndex
                    },
            
                    slideChangeTransitionStart: () => {
                        //每个slide切换结束时也运行当前slide动画
                        swiperAnimate(this.$refs.mySwiper.$swiper)
                    }
                }
            }
        }
    },
}
</script>