Vue3+gsap实现轮播(carousel)

我们要用到gsap的ScrollToPlugin插件实现滚动的动画效果,样式用Tailwind写了一部分、手撸了一部分

效果如图
在这里插入图片描述

安装配置

npm安装gsap

1
npm install gsap

项目中配置gsap

1
2
3
4
import {<!-- --> gsap } from 'gsap'// 导入gsap到vue项目
import {<!-- --> ScrollToPlugin } from 'gsap/ScrollToPlugin'// 导入gsap插件ScrollToPlugin
gsap.registerPlugin(ScrollToPlugin)// 注册插件
//配置完成,可以使用

部分代码

抽了一部分核心代码,供参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
  <div class="w-11/12 m-auto py-10">
    <div class="text-left pb-10">
      <span class="block">欢庆永远不嫌早</span>
      <h1 class="text-4xl font-bold">推荐的音乐视频</h1>
    </div>
    <button
      v-if="scrollbar.scrollleft"
      @click="scrollleft"
      id="btn-left"
      class="absolute -left-5 bottom-44 w-10 h-10 shadow-2xl focus:outline-none rounded-full bg-white"
    ></button>
    <div
      id="VmusicCarousel"
      ref="carousel"
      class="carousel space-x-7 overflow-x-auto whitespace-nowrap"
    >
   <!-- 此处VmusicCarousel包裹一堆轮播内容 -->
   ...
    </div>
    <button
      v-if="scrollbar.scrollright"
      @click="scrollright"
      id="btn-right"
      class="absolute -right-5 bottom-44 w-10 h-10 shadow-2xl focus:outline-none rounded-full bg-white"
    ></button>
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<script>
import {<!-- --> reactive, ref } from 'vue'
import {<!-- --> gsap } from 'gsap'
import {<!-- --> ScrollToPlugin } from 'gsap/ScrollToPlugin'
gsap.registerPlugin(ScrollToPlugin)
export default {<!-- -->
  name: 'VmusicCarousel',
  setup () {<!-- -->
    const carousel = ref(null)
    const scrollbar = reactive({<!-- -->
      value: 0,
      scrollleft: false,
      scrollright: true
 })

    function scrollright () {<!-- -->
      if (!scrollbar.scrollleft) {<!-- -->
        scrollbar.value = 0
        scrollbar.scrollleft = true
      }// 最左边时执行
      if (carousel.value.scrollWidth - scrollbar.value <= 2 * carousel.value.offsetWidth) {<!-- -->
        gsap.to(carousel.value, {<!-- --> duration: 0.7, scrollTo: {<!-- --> x: carousel.value.scrollWidth - carousel.value.offsetWidth }, ease: 'power2.inOut' })
        scrollbar.scrollright = false
        return
      }
      scrollbar.value += carousel.value.offsetWidth
      gsap.to(carousel.value, {<!-- --> duration: 0.7, scrollTo: {<!-- --> x: scrollbar.value }, ease: 'power2.inOut' })
    }

    function scrollleft () {<!-- -->
      if (!scrollbar.scrollright) {<!-- -->
        scrollbar.scrollright = true
      }// 最右边时执行
      if (scrollbar.value <= carousel.value.offsetWidth) {<!-- -->
        gsap.to(carousel.value, {<!-- --> duration: 0.7, scrollTo: {<!-- --> x: 0 }, ease: 'power2.inOut' })
        scrollbar.scrollleft = false
        return
      }
      scrollbar.value -= carousel.value.offsetWidth
      gsap.to(carousel.value, {<!-- --> duration: 0.7, scrollTo: {<!-- --> x: scrollbar.value }, ease: 'power2.inOut' })
    }
    return {<!-- --> scrollright, scrollleft, scrollbar }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style lang="scss" scoped>
span {<!-- -->
  font-size: 1.1rem;
  color: #ffffff80;
}
#btn-right {<!-- -->
  background-image: url('../assets/images/right.svg');
  background-size: 1.5rem;
  background-repeat: no-repeat;
  background-position: center;
}
#btn-left {<!-- -->
  background-image: url('../assets/images/left.svg');
  background-size: 1.5rem;
  background-repeat: no-repeat;
  background-position: center;
}
.carousel::-webkit-scrollbar {<!-- -->
  display: none;
}
</style>

轮播滚动逻辑详解

即函数scrollright和scrollleft

在这里插入图片描述
图中“显示区域”在代码中为一个 ref 对象 carousel 。carousel.value`即为它对应的DOM节点。

carousel.value.offsetWidth在网页中是我们可见的包裹着全部轮播内容的“框”,图中是浅色部分。

carousel.value.scrollWidth在网页中是它内容的实际宽度,图中是深色+浅色部分。

代码中定义的scrollbar对象,其中value用来储存当前滚动到的位置(即为浅色部分左边与深色部分最左边的距离),scrollleft用来储存是否显示向左按钮,同理scrollright作用于向右按钮。

我们通过控制当前滚动到的位置,来实现轮播内容显示到不同区域。

有几种情况,我们分类讨论:

向右滚动:

正常情况下
我们每次向右滚动一段距离,距离为显示区域的宽度。每次滚动前更新当前处于位置的值。
scrollbar.value += carousel.value.offsetWidth
然后滚动到该位置
gsap.to(carousel.value, { duration: 0.7, scrollTo: { x: scrollbar.value }, ease: 'power2.inOut' })

当右边深色部分<=显示区域宽度时
在这里插入图片描述

向右滚动距离应为carousel.value.scrollWidth - carousel.value.offsetWidth,即右边深色部分的宽度。
使用gsap.to进行滚动
gsap.to(carousel.value, { duration: 0.7, scrollTo: { x: carousel.value.scrollWidth - carousel.value.offsetWidth }, ease: 'power2.inOut' })
此时隐藏向右按钮

向左滚动:

正常情况下
我们每次向左滚动一段距离,距离为显示区域的宽度。每次滚动前更新当前处于位置的值。
scrollbar.value -= carousel.value.offsetWidth
然后滚动到该位置
gsap.to(carousel.value, { duration: 0.7, scrollTo: { x: scrollbar.value }, ease: 'power2.inOut' })

当左边深色部分<=显示区域宽度时
在这里插入图片描述
直接滚动到0处,
gsap.to(carousel.value, { duration: 0.7, scrollTo: { x: 0 }, ease: 'power2.inOut' })
然后隐藏向左按钮
scrollbar.scrollleft = false

最后

这是正在写的音乐网站项目中的一个模块,完整项目…过些日子写完了后续会附在下方 ??