Vue组件实现景深卡片轮播示例

下面是详细的“Vue组件实现景深卡片轮播示例”的攻略。

什么是景深卡片轮播

景深卡片轮播是一种卡片轮播式的组件,与一般的卡片轮播不同之处在于它可以在拖动卡片时产生景深效果,即中心卡片会放大,两侧卡片会逐渐缩小。这种效果能够提升用户体验,使得轮播更加流畅自然。

如何实现景深卡片轮播

Vue组件可以很方便地实现景深卡片轮播。我们需要进行以下几个步骤:

1.组件基本结构搭建

我们需要先创建一个基本的Vue组件结构,包括template、script和style三个部分。template中需要包含卡片轮播的HTML结构,比如下面的代码:

<template>
  <div class="carousel">
    <div class="cards">
      <div class="card" v-for="(item, index) in list" :key="index">
        <img :src="item.src">
        <h3>{{ item.title }}</h3>
      </div>
    </div>
  </div>
</template>

上面的代码中,我们使用了Vue的v-for指令来循环渲染卡片,使用了:item指令来将数据绑定到每个卡片上。

2.新增组件data

我们需要在script中新增一个data属性,用于存储组件内的数据。具体来说,我们需要存储卡片列表和当前活跃的卡片编号,如下所示:

<script>
export default {
  data() {
    return {
      list: [ /* ... */ ], // 卡片列表
      activeIndex: 0 // 当前活跃的卡片编号
    }
  }
}
</script>

3.编写拖动事件逻辑

接下来,我们需要编写拖动事件的逻辑,在用户拖动卡片时,计算出当前拖动距离,并据此确定卡片的缩放比例和位置变化。具体步骤如下:

3.1监听鼠标/触摸事件

首先,我们需要监听用户的鼠标/触摸事件,获取拖动的距离。最简单的方式是使用Vue的@mousedown/@touchstart、@mousemove/@touchmove和@mouseup/@touchend事件,具体代码如下:

<template>
  <div class="carousel"
    @mousedown="onDragStart"
    @touchstart="onDragStart"
    @mousemove="onDragMove"
    @touchmove="onDragMove"
    @mouseup="onDragEnd"
    @touchend="onDragEnd"
  >
    <!-- 省略卡片结构代码 -->
  </div>
</template>

3.2计算拖动距离

当用户按下鼠标或触摸屏幕时,我们需要记录下此时的鼠标/触摸点的坐标,以后每次移动时计算出距离:

<script>
export default {
  // 省略其它代码...
  methods: {
    onDragStart(event) {
      this.startPos = event.clientX || event.touches[0].clientX
    },
    onDragMove(event) {
      if (!this.startPos) return
      const currentPos = event.clientX || event.touches[0].clientX
      this.dist = currentPos - this.startPos
    },
    onDragEnd() {
      this.startPos = null
      this.dist = 0
    }
  }
}
</script>

3.3计算缩放比例和位置变化

有了拖动距离之后,我们就需要根据该距离计算出每张卡片的缩放比例和位置变化了。这里我们可以使用CSS3的transform属性。下面是一个示例CSS,用于将卡片按照x轴平移:

.card {
  position: relative;
  transform: translateX(0);
}

我们需要在此基础上增加缩放比例和z-index属性,实现景深效果:

.card.active {
  z-index: 1; /* 将当前卡片置于最上层 */
  transform: translateX(0) scale(1.2); /* 放大当前卡片 */
}
.card.prev {
  z-index: 0;
  transform: translateX(calc(-100% + var(--gap))) scale(1);
}
.card.next {
  z-index: 0;
  transform: translateX(calc(100% - var(--gap))) scale(1);
}

在计算出拖动距离后,我们需要将每张卡片的样式进行调整。具体来说,我们需要在当前活跃卡片的基础上,将左侧和右侧的卡片进行平移和缩放。具体代码如下:

<script>
export default {
  // 省略其它代码...
  methods: {
    onDragMove(event) {
      // 省略获取拖动距离的代码...
      const delta = this.dist / window.innerWidth
      this.list.forEach((card, index) => {
        const distance = index - this.activeIndex + delta
        const absDistance = Math.abs(distance)
        if (absDistance > 1) {
          // 卡片距离太大,直接隐藏
          card.hidden = true
        } else {
          // 重新计算card的位置和大小
          card.hidden = false
          const scale = absDistance < 0.5 ? 1.2 - absDistance * 1.2 : 1
          const zIndex = absDistance < 0.5 ? 1 : 0
          const x = Math.min(Math.max(distance, -1), 1) * 100
          card.style.transform = `translateX(${x.toFixed(2)}%) scale(${scale.toFixed(2)})`
          card.style.zIndex = zIndex
          card.classList.remove('active', 'prev', 'next')
          if (distance < 0) {
            card.classList.add('prev')
          } else if (distance > 0) {
            card.classList.add('next')
          } else {
            card.classList.add('active')
          }
        }
      })
    },
  }
}
</script>

上面的代码中,我们使用了forEach循环遍历每个卡片,计算出它们的位置和缩放比例。然后将对应的CSS样式应用到卡片上。

4.完整代码

组件结构和完整代码如下所示:

<template>
  <div class="carousel"
    @mousedown="onDragStart"
    @touchstart="onDragStart"
    @mousemove="onDragMove"
    @touchmove="onDragMove"
    @mouseup="onDragEnd"
    @touchend="onDragEnd"
  >
    <div class="cards">
      <div class="card"
        v-for="(item, index) in list"
        :key="index"
        :class="{ active: activeIndex === index }"
        :style="{ backgroundImage: `url(${item.src})` }"
      >
        <h3>{{ item.title }}</h3>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeIndex: 0,
      startPos: null,
      dist: 0,
      list: [
        { title: 'Card 1', src: 'https://picsum.photos/300?random=1' },
        { title: 'Card 2', src: 'https://picsum.photos/300?random=2' },
        { title: 'Card 3', src: 'https://picsum.photos/300?random=3' },
        { title: 'Card 4', src: 'https://picsum.photos/300?random=4' },
        { title: 'Card 5', src: 'https://picsum.photos/300?random=5' },
      ]
    }
  },
  methods: {
    onDragStart(event) {
      this.startPos = event.clientX || event.touches[0].clientX
    },
    onDragMove(event) {
      if (!this.startPos) return
      const currentPos = event.clientX || event.touches[0].clientX
      this.dist = currentPos - this.startPos
      const delta = this.dist / window.innerWidth
      this.list.forEach((card, index) => {
        const distance = index - this.activeIndex + delta
        const absDistance = Math.abs(distance)
        if (absDistance > 1) {
          card.hidden = true
        } else {
          card.hidden = false
          const scale = absDistance < 0.5 ? 1.2 - absDistance * 1.2 : 1
          const zIndex = absDistance < 0.5 ? 1 : 0
          const x = Math.min(Math.max(distance, -1), 1) * 100
          card.style.transform = `translateX(${x.toFixed(2)}%) scale(${scale.toFixed(2)})`
          card.style.zIndex = zIndex
          card.classList.remove('active', 'prev', 'next')
          if (distance < 0) {
            card.classList.add('prev')
          } else if (distance > 0) {
            card.classList.add('next')
          } else {
            card.classList.add('active')
          }
        }
      })
    },
    onDragEnd() {
      if (Math.abs(this.dist / window.innerWidth) > 0.2) {
        this.activeIndex += this.dist > 0 ? -1 : 1
      }
      this.startPos = null
      this.dist = 0
    }
  }
}
</script>

<style scoped>
.carousel {
  overflow: hidden;
  position: relative;
}
.card {
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  border-radius: 5px;
  background-size: cover;
  background-position: center;
  position: absolute;
  top: 10px;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  width: 80%;
  height: calc(100% - 20px);
  transition: transform 0.3s ease-in-out, opacity 0.2s ease-in-out, z-index 0.2s ease-in-out;
  opacity: 1;
}
.card.active {
  z-index: 1;
  transform: translateX(0) scale(1.2);
}
.card.prev {
  z-index: 0;
  transform: translateX(calc(-100% + var(--gap))) scale(1);
}
.card.next {
  z-index: 0;
  transform: translateX(calc(100% - var(--gap))) scale(1);
}
h3 {
  position: absolute;
  bottom: 10px;
  left: 10px;
  font-size: 24px;
  font-weight: normal;
  margin: 0;
  color: #fff;
  text-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
}
@media (min-width: 768px) {
  .cards {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: hidden;
    gap: var(--gap);
    padding: 0 var(--gap);
    position: relative;
  }
  .card {
    width: 40%;
    height: auto;
    transform-origin: center center;
    opacity: 0.8;
  }
}
</style>

示例一

下面是一个使用景深卡片轮播的简单示例:

<template>
  <div class="container">
    <h1>景深卡片轮播示例</h1>
    <carousel />
  </div>
</template>

<script>
import Carousel from './Carousel.vue'

export default {
  components: {
    Carousel
  },
}
</script>

<style>
.container {
  max-width: 768px;
  margin: 0 auto;
  padding: 20px;
  box-sizing: border-box;
  font-family: sans-serif;
  text-align: center;
}
</style>

上面的代码中,我们引用了另一个文件中的Carousel组件,并使用它来展示一组图片。

示例二

下面是一个稍微复杂一些的使用景深卡片轮播的示例:

<template>
  <div class="container">
    <h1>景深卡片轮播示例</h1>
    <carousel :list="items" />
  </div>
</template>

<script>
import Carousel from './Carousel.vue'

export default {
  components: {
    Carousel
  },
  data() {
    return {
      items: [
        { title: 'Card 1', src: 'https://cdn.pixabay.com/photo/2021/03/22/20/59/deer-6114771_960_720.jpg' },
        { title: 'Card 2', src: 'https://cdn.pixabay.com/photo/2021/03/18/12/15/horse-6103053_960_720.jpg' },
        { title: 'Card 3', src: 'https://cdn.pixabay.com/photo/2021/03/03/06/13/cat-6069625_960_720.jpg' },
        { title: 'Card 4', src: 'https://cdn.pixabay.com/photo/2020/02/27/11/02/squirrel-4888356_960_720.jpg' },
        { title: 'Card 5', src: 'https://cdn.pixabay.com/photo/2021/01/23/08/28/road-5933362_960_720.jpg' },
        { title: 'Card 6', src: 'https://cdn.pixabay.com/photo/2021/03/19/14/58/spring-6106911_960_720.jpg' },
        { title: 'Card 7', src: 'https://cdn.pixabay.com/photo/2016/12/13/05/15/puppy-1903313_960_720.jpg' },
        { title: 'Card 8', src: 'https://cdn.pixabay.com/photo/2021/03/22/10/40/flowers-6113829_960_720.jpg' },
        { title: 'Card 9', src: 'https://cdn.pixabay.com/photo/2016/01/14/18/54/piano-1149029_960_720.jpg' },
      ]
    }
  }
}
</script>

<style>
.container {
  max-width: 768px;
  margin: 0 auto;
  padding: 20px;
  box-sizing: border-box;
  font-family: sans-serif;
  text-align: center;
}
</style>

上面的代码中,我们自己生成了一组图片,并将它们设置为Carousel组件的属性,从而展示一组美丽的图片。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue组件实现景深卡片轮播示例 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • inline-block空隙之css letter-spacing与字体大小/字体关系数据表

    一、inline-block空隙 当使用inline-block元素时,其间会出现一定的空隙,这个空隙的产生是由于HTML中换行符和空格符等的缘故。因此,为了去除inline-block之间的空隙,我们可以做如下的处理: 1.设置父元素的font-size=0 .parent { font-size: 0; } .child { display: inlin…

    css 2023年6月9日
    00
  • AngularJS 与Bootstrap实现表格分页实例代码

    我们来讲解一下使用AngularJS和Bootstrap实现表格分页的完整攻略。 首先,我们需要明确一下,AngularJS是一个JavaScript框架,用于构建单页应用程序(Single Page Application),而Bootstrap是一套基于HTML、CSS和JS的开源前端框架,用于响应式设计和快速开发。 在使用AngularJS和Boots…

    css 2023年6月9日
    00
  • SpringBoot无法访问/static下静态资源的解决

    当使用SpringBoot开发web应用时,我们可以把静态资源文件放在项目中的“/static”或“/public”或“/resources”或“/META-INF/resources”目录下,在应用运行时就可以通过相应的URL来访问静态资源。然而,有时候我们会遇到这样的问题:通过URL访问静态资源时,却发现无法获取到资源,出现404错误,这通常是因为Spr…

    css 2023年6月10日
    00
  • Bootstrap一款超好用的前端框架

    Bootstrap一款超好用的前端框架 什么是Bootstrap? Bootstrap是Twitter开源的一款前端框架,它能够让开发者快速、简洁的构建响应式的Web页面,具有例如网格系统、基础样式、JavaScript插件等特性。可以让开发者更专注于网站的功能和美感,而不必乱花精力去设计一些琐碎的东西。 为什么要使用Bootstrap? 快速构建响应式网页…

    css 2023年6月9日
    00
  • 20点提高网站访问速度缩短网页加载时间!

    20点提高网站访问速度缩短网页加载时间攻略 为了提升用户体验、降低用户等待时间、提高搜索引擎排名等等,加速网站访问速度是至关重要的一个环节,特别是随着移动设备逐渐普及,用户对访问速度的要求愈发严苛。在这里,我们分享一些提高网站访问速度的通用建议,目标是缩短网页加载时间。请注意,不同站点存在差异,具体操作方式可能因网站的主要内容、主要受众,运营方式等不同而异。…

    css 2023年6月9日
    00
  • GoJs图形绘图模板Shape示例详解

    以下是关于“GoJs图形绘图模板Shape示例详解”的攻略。 什么是GoJs图形绘图模板Shape GoJs图形绘图模板Shape是一个JavaScript图形库,它可以用于创建各种可交互的图形,包括流程图、组织结构图、网络拓扑图等。 Shape模板示例1 下面我们来看一个GoJs Shape模板的示例,该示例用于创建带有箭头的线条。首先,我们需要定义一个S…

    css 2023年6月10日
    00
  • 常用js,css文件统一加载方法(推荐) 并在加载之后调用回调函数

    常用js、css文件统一加载方法的实现 为了加快网页的加载速度,我们可以采用常用js、css文件统一加载方法。这种方法可以将多个js、css文件打包成一个文件,从而减少HTTP请求次数。以下是一种实现这种方法的方式: function loadResources(urls, callback) { var resources = urls.length, l…

    css 2023年6月10日
    00
  • CSS过渡效果

    CSS过渡(Transition)是一种常见的动画效果,用于控制元素在某些条件下的改变(如鼠标悬停、元素聚焦等),从而使页面的交互更加生动。 在本文中,我们将详细介绍CSS过渡的三个主要方面:过渡属性、过渡时间和过渡函数,并提供具体的代码示例。 1. 过渡属性 过渡属性用于指定需要被过渡的CSS属性,可以是单个属性,也可以是多个属性,多个属性之间以逗号分隔。…

    Web开发基础 2023年3月30日
    00
合作推广
合作推广
分享本页
返回顶部