大屏处理
This commit is contained in:
324
src/views/recruitment/components/carousel.vue
Normal file
324
src/views/recruitment/components/carousel.vue
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
<template>
|
||||||
|
<div class="swiper-container">
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
<div
|
||||||
|
class="swiper-slide"
|
||||||
|
:class="getSlideClass(index)"
|
||||||
|
v-for="(slide, index) in slides"
|
||||||
|
:key="index"
|
||||||
|
:style="getSlideStyle(index)"
|
||||||
|
>
|
||||||
|
<!-- 使用具名插槽传递每个slide的内容和索引 -->
|
||||||
|
<div class="slide-content">
|
||||||
|
<div class="slide-image">
|
||||||
|
<slot name="slide" :slide="slide" :index="index" />
|
||||||
|
</div>
|
||||||
|
<!-- <div class="slide-text">-->
|
||||||
|
<!-- <h3>{{ slide.title }}</h3>-->
|
||||||
|
<!-- <p>{{ slide.description }}</p>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="swiper-controls">-->
|
||||||
|
<!-- <button class="swiper-button" @click="prevSlide">←</button>-->
|
||||||
|
<!-- <button class="swiper-button" @click="nextSlide">→</button>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="swiper-pagination">-->
|
||||||
|
<!-- <div-->
|
||||||
|
<!-- class="pagination-bullet"-->
|
||||||
|
<!-- v-for="(slide, index) in slides"-->
|
||||||
|
<!-- :key="index"-->
|
||||||
|
<!-- :class="{ active: currentIndex === index }"-->
|
||||||
|
<!-- @click="goToSlide(index)"-->
|
||||||
|
<!-- ></div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent, onMounted, onBeforeUnmount, ref } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Carousel',
|
||||||
|
props: {
|
||||||
|
slides: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => [
|
||||||
|
{
|
||||||
|
title: '左侧卡片',
|
||||||
|
description: '淡入效果从左侧进入',
|
||||||
|
image: 'https://via.placeholder.com/600x400/3498db/ffffff?text=Left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '中间卡片',
|
||||||
|
description: '淡入效果居中放大',
|
||||||
|
image: 'https://via.placeholder.com/600x400/e74c3c/ffffff?text=Center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '右侧卡片',
|
||||||
|
description: '淡入效果从右侧进入',
|
||||||
|
image: 'https://via.placeholder.com/600x400/2ecc71/ffffff?text=Right'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
autoPlayInterval: {
|
||||||
|
type: Number,
|
||||||
|
default: 5000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const currentIndex = ref(0)
|
||||||
|
const autoPlayTimer = ref(null)
|
||||||
|
|
||||||
|
const getSlideClass = (index) => {
|
||||||
|
const diff = index - currentIndex.value
|
||||||
|
if (diff === 0) return 'center'
|
||||||
|
if (diff === -1 || (currentIndex.value === 0 && index === props.slides.length - 1)) return 'left'
|
||||||
|
if (diff === 1 || (currentIndex.value === props.slides.length - 1 && index === 0)) return 'right'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSlideStyle = (index) => {
|
||||||
|
const diff = index - currentIndex.value
|
||||||
|
if (
|
||||||
|
Math.abs(diff) > 1 &&
|
||||||
|
!(currentIndex.value === 0 && index === props.slides.length - 1) &&
|
||||||
|
!(currentIndex.value === props.slides.length - 1 && index === 0)
|
||||||
|
) {
|
||||||
|
return { display: 'none' }
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevSlide = () => {
|
||||||
|
currentIndex.value = (currentIndex.value - 1 + props.slides.length) % props.slides.length
|
||||||
|
resetAutoPlay()
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextSlide = () => {
|
||||||
|
currentIndex.value = (currentIndex.value + 1) % props.slides.length
|
||||||
|
resetAutoPlay()
|
||||||
|
}
|
||||||
|
|
||||||
|
const goToSlide = (index) => {
|
||||||
|
currentIndex.value = index
|
||||||
|
resetAutoPlay()
|
||||||
|
}
|
||||||
|
|
||||||
|
const startAutoPlay = () => {
|
||||||
|
pauseAutoPlay()
|
||||||
|
autoPlayTimer.value = window.setInterval(() => {
|
||||||
|
nextSlide()
|
||||||
|
}, props.autoPlayInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pauseAutoPlay = () => {
|
||||||
|
if (autoPlayTimer.value) {
|
||||||
|
clearInterval(autoPlayTimer.value)
|
||||||
|
autoPlayTimer.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetAutoPlay = () => {
|
||||||
|
pauseAutoPlay()
|
||||||
|
startAutoPlay()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// const container = document.querySelector('.swiper-container')
|
||||||
|
// if (container) {
|
||||||
|
// container.addEventListener('mouseenter', pauseAutoPlay)
|
||||||
|
// container.addEventListener('mouseleave', startAutoPlay)
|
||||||
|
// }
|
||||||
|
// startAutoPlay()
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
const container = document.querySelector('.swiper-container')
|
||||||
|
if (container) {
|
||||||
|
container.removeEventListener('mouseenter', pauseAutoPlay)
|
||||||
|
container.removeEventListener('mouseleave', startAutoPlay)
|
||||||
|
}
|
||||||
|
pauseAutoPlay()
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentIndex,
|
||||||
|
getSlideClass,
|
||||||
|
getSlideStyle,
|
||||||
|
prevSlide,
|
||||||
|
nextSlide,
|
||||||
|
goToSlide
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-container {
|
||||||
|
width: 17.03125vw;
|
||||||
|
position: relative;
|
||||||
|
//padding: 2.083vw 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-wrapper {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
//height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide {
|
||||||
|
width: 17.03125vw;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide.left {
|
||||||
|
left: 2vw;
|
||||||
|
transform: scale(0.9);
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0.8;
|
||||||
|
animation: fadeInLeft 0.5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide.center {
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%) scale(1);
|
||||||
|
z-index: 2;
|
||||||
|
opacity: 0;
|
||||||
|
animation: fadeInCenter 0.5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide.right {
|
||||||
|
right: 2vw;
|
||||||
|
transform: scale(0.9);
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0.8;
|
||||||
|
animation: fadeInRight 0.5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInLeft {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.8) translateX(-20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: scale(0.9) translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInCenter {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-50%) scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(-50%) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInRight {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.8) translateX(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: scale(0.9) translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
background: white;
|
||||||
|
border-radius: 0.208vw;
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-image {
|
||||||
|
background: url("~@/assets/recruitment/card_bg.svg") no-repeat;
|
||||||
|
height: 16.5625vw;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-text {
|
||||||
|
padding: 20px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-text h3 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-text p {
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #333;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
margin: 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button:hover {
|
||||||
|
background: #555;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-pagination {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-bullet {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ccc;
|
||||||
|
margin: 0 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-bullet.active {
|
||||||
|
background: #333;
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
</style>
|
Reference in New Issue
Block a user