实现如下效果
定义子组件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,
animating: false,
opacity: 1
};
},
methods: {
processIndex(index, activeIndex, length) {
if ((activeIndex === 0 || activeIndex === 1) && index === length - 1) {
return -1;
} else if ((activeIndex === 0 || activeIndex === 1) && index === length - 2) {
return -2;
} else if ((activeIndex === length - 1 || activeIndex === length - 2) && index === 0) {
return length;
} else if ((activeIndex === length - 1 || activeIndex === length - 2) && 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' && oldIndex !== undefined) {
this.animating = index === activeIndex || index === oldIndex;
}
if (index !== activeIndex && length > 3 && 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 && 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 && this.$parent.updateItems();
},
destroyed() {
this.$parent && this.$parent.updateItems();
}
};
</script>
父组件引用此组件即可
<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: '测试1' },
{ photo: require('../../../assets/images/manage/projectView/auxiliary/2.png'), title: '测试2' },
{ photo: require('../../../assets/images/manage/projectView/auxiliary/3.png'), title: '测试3' },
{ photo: require('../../../assets/images/manage/projectView/auxiliary/4.png'), title: '测试4' },
{ photo: require('../../../assets/images/manage/projectView/auxiliary/5.png'), title: '测试5' },
{ photo: require('../../../assets/images/manage/projectView/auxiliary/6.png'), title: '测试6' },
{ photo: require('../../../assets/images/manage/projectView/auxiliary/7.png'), title: '测试7' }]
}
}
}
</script lang="scss" scoped>
<style>
::v-deep.el-carousel__item--card {
width: 20%;
}
.imgBox {
width: 100%;
img {
width: 100%;
}
}
</style>