Achieve the following effect
Define subcomponent Swiper.vue
<template> <div v-show="ready" class="el-carousel__item" :class="{ 'is-active': active, 'el-carousel__item--card': $parent.type === 'card', 'is-in-stage': inStage, 'is-hover': hover, 'is-animating': animating }" @click="handleItemClick" :style="itemStyle"> <!-- <div v-if="$parent.type === 'card'" v-show="!active" class="el-carousel__mask"> </div> --> <slot></slot> </div> </template> <script> import { autoprefixer } from 'element-ui/src/utils/util'; const CARD_SCALE = 0.83; const CARD_SCALE2 = 0.7; export default { name: 'ElCarouselItem', props: { name: String, label: { type: [String, Number], default: '' } }, data() { return { hover: false, translate: 0, scale: 1, active: false, ready: false, inStage: false, animation: false, Opacity: 1 }; }, methods: { processIndex(index, activeIndex, length) { if ((activeIndex === 0 || activeIndex === 1) & amp; & amp; index === length - 1) { return -1; } else if ((activeIndex === 0 || activeIndex === 1) & amp; & amp; index === length - 2) { return -2; } else if ((activeIndex === length - 1 || activeIndex === length - 2) & amp; & amp; index === 0) { return length; } else if ((activeIndex === length - 1 || activeIndex === length - 2) & amp; & amp; index === 1) { return length + 1; } return index; }, calcCardTranslate(index, activeIndex) { const parentWidth = this.$parent.$el.offsetWidth; if (this.inStage) { return parentWidth * ((index - activeIndex) + 2) / 5; } else if (index < activeIndex) { return 0 * parentWidth / 5; } else { return 4 * parentWidth / 5; } }, calcTranslate(index, activeIndex, isVertical) { const distance = this.$parent.$el[isVertical ? 'offsetHeight' : 'offsetWidth']; return distance * (index - activeIndex); }, translateItem(index, activeIndex, oldIndex) { const parentType = this.$parent.type; const parentDirection = this.parentDirection; const length = this.$parent.items.length; if (parentType !== 'card' & amp; & amp; oldIndex !== undefined) { this.animating = index === activeIndex || index === oldIndex; } if (index !== activeIndex & amp; & amp; length > 3 & amp; & amp; this.$parent.loop) { index = this.processIndex(index, activeIndex, length); } if (parentType === 'card') { if (parentDirection === 'vertical') { console.warn('[Element Warn][Carousel]vertical direction is not supported in card mode'); } this.inStage = Math.round(Math.abs(index - activeIndex)) <= 1; this.active = index === activeIndex; this.translate = this.calcCardTranslate(index, activeIndex); if (this.active) { this.scale = 1 this.opacity = 1 } else if (Math.abs(index - activeIndex) == 1) { this.scale = CARD_SCALE; this.opacity = 0.6 } else { this.scale = CARD_SCALE2; if (Math.abs(index - activeIndex) == 2) { this.opacity = 0.4 } else { this.opacity = 0 } } console.log(index, activeIndex) } else { this.active = index === activeIndex; const isVertical = parentDirection === 'vertical'; this.translate = this.calcTranslate(index, activeIndex, isVertical); this.scale = 1; } this.ready = true; }, handleItemClick() { const parent = this.$parent; if (parent & amp; & amp; parent.type === 'card') { const index = parent.items.indexOf(this); parent.setActiveItem(index); } } }, computed: { parentDirection() { return this.$parent.direction; }, itemStyle() { const translateType = this.parentDirection === 'vertical' ? 'translateY' : 'translateX'; const value = `${translateType}(${this.translate}px) scale(${this.scale})`; const style = { transform: value, opacity: this.opacity }; return autoprefixer(style); } }, created() { this.$parent & amp; & amp; this.$parent.updateItems(); }, destroyed() { this.$parent & amp; & amp; this.$parent.updateItems(); } }; </script>
The parent component can reference this component
<template> <el-carousel :interval="3000" type="card" height="320px" :autoplay="false" style="width: 70vw;"> <SwiperItem v-for="(item, i) in dataList" :key="i"> <div class="imgBox"> <img class="imgItem" :src="item.photo" alt="" srcset="" /> <div class="imgTit">{<!-- -->{ item.title }}</div> </div> </SwiperItem> </el-carousel> </template> <script> import SwiperItem from "@/components/Swiper/item.vue" export default { components: { SwiperItem }, data() { return { dataList: [ { photo: require('../../../assets/images/manage/projectView/auxiliary/1.png'), title: 'Test 1' }, { photo: require('../../../assets/images/manage/projectView/auxiliary/2.png'), title: 'Test 2' }, { photo: require('../../../assets/images/manage/projectView/auxiliary/3.png'), title: 'Test 3' }, { photo: require('../../../assets/images/manage/projectView/auxiliary/4.png'), title: 'Test 4' }, { photo: require('../../../assets/images/manage/projectView/auxiliary/5.png'), title: 'Test 5' }, { photo: require('../../../assets/images/manage/projectView/auxiliary/6.png'), title: 'Test 6' }, { photo: require('../../../assets/images/manage/projectView/auxiliary/7.png'), title: 'Test 7' }] } } } </script lang="scss" scoped> <style> ::v-deep.el-carousel__item--card { width: 20%; } .imgBox { width: 100%; img { width: 100%; } } </style>