html template 部分:
<!-- banner 滚动 -->
<transition v-if="state.bannerList.length" name="fade">
<swiper
:autoplay="{
delay: 2000,
disableOnInteraction: false,
}"
:effect="'carousel'"
:grabCursor="true"
:slides-per-view="'auto'"
:loop="true"
:pagination="{
clickable: true,
}"
navigation
:modules="state.bannerModules"
@beforeInit="onCarouselBeforeInit"
@progress="onCarouselProgress"
@setTransition="onCarouselSetTranistion"
>
<swiper-slide v-for="(item, index) in state.bannerList" :key="index">
<div class="swiper-carousel-animate-opacity">
<img class="image" :src="item.resourcesPicture" />
</div>
</swiper-slide>
</swiper>
</transition>
less 部分:
.swiper-carousel {
position: relative;
margin: 10px auto 30px;
// max-width: @custom-screen-width;
width: 100%;
height: 358px;
.swiper-slide {
width: 900px;
height: 358px;
border-radius: 16px;
background: #18212b;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.2);
// max-width: calc(100% - 48px);
}
.swiper-carousel-animate-opacity {
height: 100%;
}
.swiper-pagination-bullets {
bottom: 0;
}
img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
border-radius: 16px;
}
.slide-content {
position: absolute;
left: 0;
width: 100%;
bottom: 0;
padding: 88px 16px 24px;
box-sizing: border-box;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75));
border-radius: 0 0 8px 8px;
}
@media (max-width: 640px) {
.swiper-button-next,
.swiper-button-prev {
display: none !important;
}
}
:deep(.swiper-pagination-bullet) {
&-active {
background-color: #fff;
}
}
:deep(.swiper-button-prev),
:deep(.swiper-button-next) {
color: #fff;
}
}
ts 部分:
import "swiper/less/navigation";
import "swiper/less/pagination";
import "swiper/less";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Pagination, Navigation, Autoplay } from "swiper/modules";
const state = reactive({
bannerList: [] as { resourcesPicture: string }[],
bannerModules: [Pagination, Navigation, Autoplay],
})
/**
* 主banner 加载之前
* @returns {*}
*/
const onCarouselBeforeInit = (swiper) => {
try {
const currentSwiperStr = "carousel";
if (swiper.params.effect !== currentSwiperStr) return;
swiper.classNames.push(
swiper.params.containerModifierClass + currentSwiperStr
);
const options = {
watchSlidesProgress: !0,
centeredSlides: !0,
};
Object.assign(swiper.params, options);
Object.assign(swiper.originalParams, options);
} catch (error) {
console.log("swiper init", error);
}
};
/**
* 主banner
* @returns {*}
*/
const onCarouselProgress = (swiper) => {
try {
if (swiper.params.effect !== "carousel") return;
const slidesCount = swiper.slides.length;
for (let index = 0; index < slidesCount; index++) {
const currentSlide = swiper.slides[index],
progress = swiper.slides[index].progress,
opacity = Math.abs(progress);
let number = 1;
opacity > 1 && (number = 0.3 * (opacity - 1) + 1);
const elementOpacity = currentSlide.querySelectorAll(
".swiper-carousel-animate-opacity"
),
percenter =
progress * number * 55 * (swiper.rtlTranslate ? -1 : 1) + "%",
scale = 1 - 0.25 * opacity,
zIndex = slidesCount - Math.abs(Math.round(progress));
(currentSlide.style.transform = `translateX(${percenter}) scale(${scale})`),
(currentSlide.style.zIndex = zIndex),
(currentSlide.style.opacity = opacity > 3 ? 0 : 1),
elementOpacity.forEach(
(item) => (item.style.opacity = 1 - opacity / 3)
);
}
} catch (error) {
console.log("swiper progress", error);
}
};
/**
* 主banner transition
* @returns {*}
*/
const onCarouselSetTranistion = (swiper, time) => {
if (swiper.params.effect !== "carousel") return;
for (let index = 0; index < swiper.slides.length; index++) {
const currentSlide = swiper.slides[index],
element = currentSlide.querySelectorAll(
".swiper-carousel-animate-opacity"
);
(currentSlide.style.transitionDuration = `${time}ms`),
element.forEach((item) => (item.style.transitionDuration = `${time}ms`));
}
};