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

yizhihongxing

下面是详细的“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日

相关文章

  • jquery tools系列 expose 学习

    jQuery Tools系列之Exposure学习攻略 Exposure是jQuery Tools插件系列中一个非常实用的插件。它能帮助我们以非常简单、优美的方式展示一个弹出式的遮罩层,以实现各种场景下的交互。 资源准备 为了开始学习Exposure,我们需要先准备一些资源: jQuery:Exposure依赖于jQuery库,所以我们需要先引入jQuery…

    css 2023年6月10日
    00
  • jQuery代码实现发展历程时间轴特效

    jQuery代码实现发展历程时间轴特效 简介 时间轴是一个常用的展示历史发展进程的方式,而jQuery是一个广受欢迎的JavaScript库,能够轻松实现各种页面特效。本文将详细介绍如何使用jQuery实现发展历程时间轴特效,包括主要的HTML结构、CSS样式和jQuery代码实现。 HTML结构 首先,我们需要组织出一个基本的HTML结构,用于展现时间轴的…

    css 2023年6月11日
    00
  • CSS3 透明色 RGBA使用介绍

    CSS3 透明色 RGBA使用介绍 CSS3中的透明色可以使用RGBA值来表示,其中R、G、B表示红、绿、蓝三原色的值,A表示透明度的值。RGBA值的取值范围为0~255,透明度的取值范围为0~1。本攻略将详细讲解CSS3透明色RGBA的使用介绍,包括基本概念、属性介绍、注意事项和示例说明。 1. 基本概念 CSS3中的透明色可以使用RGBA值来表示,其中R…

    css 2023年5月18日
    00
  • VUE中filters过滤器的两种用法实例

    我们来讲解一下“VUE中filters过滤器的两种用法实例”。 什么是过滤器(Filter) 在Vue中,我们经常使用过滤器(Filter)来格式化文本、数字、日期等数据。Vue的过滤器可以全局注册、局部注册以及内联使用等多种方式,非常灵活。 Vue中的过滤器是一个函数,在模板中调用,将数据进行过滤,最后输出处理后的结果。过滤器可以接受任意数量的输入参数,并…

    css 2023年6月10日
    00
  • 使用CodeMirror实现Python3在线编辑器的示例代码

    使用CodeMirror实现Python3在线编辑器的示例代码攻略: 步骤1:引入CodeMirror库 第一步是引入CodeMirror库,这个库是为了实现在线编辑器功能而设计的,可以方便地实现语法高亮、代码折叠、缩进、自动完成等功能。可以通过以下代码引入CodeMirror库: <link rel="stylesheet" hr…

    css 2023年6月10日
    00
  • 用 CSS background 实现刻度线的呈现

    用 CSS background 实现刻度线的呈现,可以通过利用相关CSS属性和技巧实现,下面是具体步骤: 步骤一: 制作刻度线图案 首先,我们需要建立一个背景图案作为刻度线,具体制作方法如下: 通过ps或者其他图片编辑工具,建立一个宽度为1像素、高度为10像素的透明背景图片。 分成两个部分,一个是白色刻度线,一个是灰色背景,分别涂上颜色。 将两个部分分别保…

    css 2023年6月9日
    00
  • 使用canvas制作炫酷黑客帝国数字雨背景html+css+js

    讲解如下: 组件原理 使用canvas制作炫酷黑客帝国数字雨背景需要掌握以下知识点: HTML5 Canvas HTML5 Canvas是HTML中的一个标签,可用于绘制图形(如矩形、三角形、圆形、文字等)。 JavaScript JavaScript是一种脚本语言,通常用于在网页中添加交互效果与动态功能。 根据上面提到的知识点,我们可以实现一个基本的”数字…

    css 2023年6月9日
    00
  • 如何用原生js写一个弹窗消息提醒插件

    如何用原生JavaScript写一个弹窗消息提醒插件: 需要实现的功能我们需要写一个弹窗插件,可以根据传入的参数来动态调整弹窗的显示内容和样式。弹窗需要包含以下功能: 显示特定的消息,并根据消息类型展示不同的图标 显示不同类型消息对应的背景颜色和字体颜色 提供一个可控制的时间参数,可以设置多久后自动关闭弹窗,如果不设置时间则需要点击弹窗才能关闭 提供一个可选…

    css 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部