全屏滚动之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. 全屏滚动效果图
二、 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. 最终效果
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>