uniapp 电影卡片式轮播图

88 阅读1分钟

uniapp 插件地址:ext.dcloud.net.cn/plugin?id=1…

<template>
    <view class="movie-swiper-container">
	      <cardSwiper
	        :movie-list="movieList" 
	        margin="250rpx"
			 @change="handleSwiperChange"
	      />
    </view>
</template>
<script setup>

import cardSwiper from "./components/helang-cardSwiper/helang-cardSwiper"
// 电影数据
const movieList = ref([
     {
       cover: "http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024",
       title: "浪浪山小妖怪",
       score: "9.2",
       duration: "120分钟",
       genre: "动画",
       cast: "国产"
     },
     {
       cover: "http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024",
       title: "731",
       score: "8.5",
       duration: "150分钟",
       genre: "历史",
       cast: "战争"
     },
     {
       cover: "http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024",
       title: "捕风捉影",
       score: "9.6",
       duration: "125分钟",
       genre: "剧情",
       cast: "姜武、王志文"
     },
     {
       cover: "http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024",
       title: "盖世英雄",
       score: "8.8",
       duration: "90分钟",
       genre: "喜剧",
       cast: "国产"
     }
]);
// 这是helang-cardSwiper.vue的代码,我在原作者基础上修改了一下
<template>
  <view>
    <view class="top-swiper">
      <view class="box">
        <view style="height: 10px;"></view>
        <swiper 
          class="swiper" 
          :previous-margin="swiper.margin" 
          :next-margin="swiper.margin" 
          :circular="true" 
          @change="swiperChange"
        >
          <swiper-item v-for="(item, index) in movieList" :key="index">
            <image 
              class="le-img" 
              :src="item.cover" 
              :class="{'le-active': swiper.index === index}"
            ></image>
          </swiper-item>
        </swiper>
      </view>
    </view>
    <!-- 当前影片信息 -->
    <view class="movie-info" v-if="currentMovie">
      <text class="movie-title">{{ currentMovie.title }}</text>
      <text class="movie-score">评分:{{ currentMovie.score }}</text>
      <view class="movie-desc">{{ currentMovie.duration }} | {{ currentMovie.genre }} | {{ currentMovie.cast }}</view>
    </view>
  </view>
</template>

<script setup>
import { ref, computed } from 'vue';
import { defineProps, defineEmits } from 'vue';
// 定义要抛出的事件
const emits = defineEmits(['change']);
// 定义接收的props
const props = defineProps({
  // 影片列表数据(必传)
  movieList: {
    type: Array,
    required: true,
    default: () => [] // 默认空数组
  },
  // 轮播边距(可选,默认250rpx)
  margin: {
    type: String,
    default: "250rpx"
  }
});

// 轮播内部状态
const swiper = ref({
  index: 0, // 当前激活索引
  margin: props.margin // 从props接收边距
});

// 轮播切换事件
const swiperChange = (e) => {
  swiper.value.index = e.detail.current;
    // 向父组件发送事件,传递当前索引
	emits('change', swiper.value.index);
};

// 计算当前影片信息
const currentMovie = computed(() => {
  return props.movieList[swiper.value.index] || null;
});
</script>

<style lang="scss">
.top-swiper {
  margin-bottom: 30rpx;

  .box {
    padding-top: var(--status-bar-height);
    box-sizing: content-box;
    width: 100%;
    height: auto;
  }

  .swiper {
    height: 280rpx;
    margin: 0 20rpx;

    .le-img {
      width: 200rpx;
      height: 100%;
      display: block;
      transform: scale(0.9);
      transition: transform 0.3s ease-in-out 0s;
      border-radius: 4px;

      &.le-active {
        transform: scale(1);
      }
    }
  }
}

.movie-info {
  text-align: center;

  .movie-title {
    font-size: 32rpx;
    font-weight: bold;
    color: #333;
  }

  .movie-score {
    margin-left: 10rpx;
    color: #f53f3f;
    font-size: 28rpx;
  }

  .movie-desc {
    font-size: 24rpx;
    color: #666;
  }
}
</style>
    
    

image.png

image.png