更新记录

1.0.0(2026-10-07) 下载此版本

[1.0.0] - 2026-08-25

新增

  • 首次发布
  • 支持卡片堆叠展示
  • 支持手势左右滑动
  • 支持无限循环
  • 支持自动播放
  • 支持点击事件回调
  • 支持配置缩放、偏移、旋转、透明度等参数

平台兼容性

uni-app(3.8.5)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Chrome插件版本 Safari Safari插件版本 app-vue app-nvue Android iOS 鸿蒙
√ 1.0.0 √ 1.0.0 √ 1.0.0 √ 1.0.0 √ √ √ √ √
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ √ √ √ √ √ √ √ √ √ √ √

CardStack 卡片堆叠组件

一款支持手势拖拽滑动、无限循环、自动播放的卡片堆叠组件,适用于 Tinder 式卡片交互、商品推荐、AI 问答等场景。

特性

  • ✅ 手势拖拽滑动(左右切换卡片)
  • ✅ 无限循环 / 有限模式
  • ✅ 自动播放(可配置间隔)
  • ✅ 用户交互后暂停 / 恢复自动播放
  • ✅ 堆叠错落效果(缩放、偏移、旋转、透明度可配置)
  • ✅ 点击事件回调
  • ✅ 兼容 App / H5 / 微信小程序全平台

基本使用

<template>
  <view class="page">
    <card-stack
      ref="cardStack"
      :items="reviewList"
        height="520rpx"
        :loop="true"
        :autoplay="true"
        :stopOnUserSwipe="false"
        :duration="300"
        :stack-depth="3"
        :stack-offset-x="10"
        :stack-offset-y="8"
        :stack-scale-step="0.025"
        :max-rotate="60"
        :swipe-threshold="0.22"
        :short-swipe-velocity="0.45"
        @change="onCardChange"
        @cardClick="onRightCardClick"
    >
    <template #card="{ item }">
        <view class="review-card">
          <view class="review-card__header">
            <!-- <image
              class="avatar"
              :src="item.avatar"
              mode="aspectFill"
            /> -->
            <view class="user-info">
              <view class="name">
                {{ item.name }}
              </view>
              <view class="age">
                {{ item.age }}岁 | {{ item.gender }}
              </view>
            </view>
          </view>
          <view class="review-card__content">
            {{ item.content }}
          </view>
          <view class="review-card__button">
            购买同款
          </view>
        </view>
    </template>
    </card-stack>
  </view>
</template>

<script>
export default {
  data() {
    return {
      reviewList: [
        {
          id: 1,
          avatar: '/static/avatar/1.png',
          name: 'j的name',
          age: 42,
          gender: '男',
          content: '效果真的不错,每天两粒,吃了快一个月。'
        },
        {
          id: 2,
          avatar: '/static/avatar/2.png',
          name: '阿源',
          age: 38,
          gender: '男',
          content: '确实实用,现在指标已经明显下降。'
        },
        {
          id: 3,
          avatar: '/static/avatar/3.png',
          name: '王先生',
          age: 31,
          gender: '男',
          content: '坚持使用了一段时间,整体感觉不错。'
        },
        {
          id: 4,
          avatar: '/static/avatar/4.png',
          name: 'JamesCard',
          age: 42,
          gender: '男',
          content: '连续使用之后效果比较明显。'
        }
      ]
    }
  },
  methods: {
    onCardChange(e) {
      console.log('当前卡片:', e.index)
      console.log('切换方向:', e.direction)
    },
    onRightCardClick(e) {
        console.log('当前卡片:', e.index)
    },
  }
}
</script>

<style lang="scss" scoped>
.page {
  padding: 30rpx;
}

.review-card {
  height: 100%;
  box-sizing: border-box;
  padding: 30rpx;
  background: #fff;
  border-radius: 20rpx;
  box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.08);
}

.review-card__header {
  display: flex;
  align-items: center;
}

.avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
}

.user-info {
  margin-left: 20rpx;
}

.name {
  font-size: 30rpx;
  font-weight: 600;
}

.age {
  margin-top: 8rpx;
  font-size: 24rpx;
  color: #999;
}

.review-card__content {
  margin-top: 40rpx;
  font-size: 28rpx;
  line-height: 1.8;
  color: #333;
}

.review-card__button {
  margin-top: 40rpx;
  height: 72rpx;
  line-height: 72rpx;
  text-align: center;
  border: 1px solid #ddd;
  border-radius: 36rpx;
  color: #666;
}
</style>

Props

属性 类型 默认值 说明
items Array [] 数据源列表
height String / Number '420rpx' 容器高度
initialIndex Number 0 初始索引
loop Boolean true 是否无限循环
duration Number 300 动画时长(ms)
stackDepth Number 3 堆叠层数(可见卡片数)
stackOffsetX Number 10 每层水平偏移(px)
stackOffsetY Number 8 每层垂直偏移(px)
stackScaleStep Number 0.025 每层缩放步长
maxRotate Number 7 最大旋转角度(deg)
swipeThreshold Number 0.22 滑动判定阈值(占容器宽度比例)
shortSwipeVelocity Number 0.45 快速滑动速度阈值
longSwipeMs Number 300 长按判定时间(ms)
resistance Number 0.25 边界阻尼系数
autoplay Boolean false 是否自动播放
autoplayInterval Number 3000 自动播放间隔(ms)
stopOnUserSwipe Boolean true 用户滑动后是否永久停止自动播放
resumeAutoplayDelay Number 5000 用户滑动后恢复自动播放延迟(ms)

Events

事件名 参数 说明
change { index, item, direction } 卡片切换时触发
cardClick { index, item } 点击卡片时触发

Slot

插槽名 参数 说明
card { item, index, active, position } 卡片内容自定义

Slot 参数说明

参数 说明
item 当前卡片数据
index 当前卡片索引
active 是否为当前活动卡片
position 堆叠位置(0 当前,1 下一层,-1 上一层)

方法

通过 ref 调用:

<card-stack ref="stackRef" :items="list" />

<script>
export default {
  methods: {
    goNext() {
      this.$refs.stackRef.next();  // 切换到下一张
    },
    goPrev() {
      this.$refs.stackRef.prev();  // 切换到上一张
    },
  },
};
</script>
方法 说明
next() 切换到下一张(左滑)
prev() 切换到上一张(右滑)

使用示例

1. 基础卡片堆叠

<card-stack :items="list" height="420rpx">
  <template #card="{ item }">
    <view class="card">{{ item.title }}</view>
  </template>
</card-stack>

2. 自动播放

<card-stack
  :items="list"
  :autoplay="true"
  :autoplay-interval="3000"
  height="420rpx"
>
  <template #card="{ item }">
    <view class="card">{{ item.title }}</view>
  </template>
</card-stack>

3. 用户滑动后 3 秒恢复自动播放

<card-stack
  :items="list"
  :autoplay="true"
  :autoplay-interval="3000"
  :stop-on-user-swipe="false"
  :resume-autoplay-delay="3000"
  height="420rpx"
>
  <template #card="{ item }">
    <view class="card">{{ item.title }}</view>
  </template>
</card-stack>

4. 卡片点击

<card-stack
  :items="list"
  height="420rpx"
  @cardClick="onCardClick"
>
  <template #card="{ item }">
    <view class="card">{{ item.title }}</view>
  </template>
</card-stack>

<script>
export default {
  methods: {
    onCardClick(e) {
      console.log('点击了:', e.item);
    },
  },
};
</script>

自动播放行为说明

用户操作 自动播放行为
触摸屏幕(未滑动) 暂停
滑动后回弹(没滑走) 立即恢复
滑动后滑走 stopOnUserSwipe: true 永久停止
false 延迟 resumeAutoplayDelay 后恢复
触摸但横轴判定失败 立即恢复

注意事项

  1. 卡片内容高度:建议在插槽内使用固定高度的卡片,避免布局跳动
  2. 图片性能:图片较大时建议使用 CDN 压缩参数,减少渲染开销
  3. items 变化:列表变化会自动重启自动播放
  4. loop 为 false:滑到边界时会触发回弹,不会循环

兼容性

平台 支持
App ✅
H5 ✅
微信小程序 ✅
支付宝小程序 ✅
抖音小程序 ✅

更新日志

详见 changelog.md

License

MIT

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT协议

暂无用户评论。