| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- <template>
- <section class="swiper--banner--wrapper" :data-type="type">
- <div class="swiper--banner--container">
- <!-- 30% 영역: 컨트롤 및 텍스트 -->
- <div class="swiper--controls--section">
- <div class="controls--top">
- <!-- 페이지네이션과 네비게이션 버튼 -->
- <div class="pagination--nav--wrapper">
- <div class="navigation--buttons">
- <div class="swiper-button-prev" ref="prevRef">
- <svg
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="24px"
- height="24px"
- class="sc-oVpqz cvAPSl"
- >
- <use href="/img/ico--back--s.svg#main"></use>
- </svg>
- </div>
- <div class="swiper-pagination" ref="paginationRef"></div>
- <div class="swiper-button-next" ref="nextRef">
- <svg
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="24px"
- height="24px"
- class="sc-oVpqz cvAPSl"
- >
- <use href="/img/ico--forward--s.svg#main"></use>
- </svg>
- </div>
- </div>
- </div>
- </div>
- <!-- 텍스트 컨텐츠 -->
- <div class="text--content">
- <div class="text--slider" ref="textSlider">
- <div
- v-for="(slide, index) in slides"
- :key="index"
- class="text--slide"
- :class="{ active: index === currentSlide }"
- >
- <h2 v-if="getSlideTitle(index)" class="main--title">
- {{ getSlideTitle(index) }}
- </h2>
- <h3 v-if="getSlideSubtitle(index)" class="sub--title">
- {{ getSlideSubtitle(index) }}
- </h3>
- <h4 v-if="getSlideSmalldesc(index)" class="desc--title">
- {{ getSlideSmalldesc(index) }}
- </h4>
- <NuxtLink
- v-if="getSlideMorelink(index)"
- class="more--detail--href mt--20"
- :to="getSlideMorelink(index)"
- >자세히 보기 <i class="ico"></i
- ></NuxtLink>
- </div>
- </div>
- <div v-if="notice" class="notice--text">
- <p>{{ notice }}</p>
- </div>
- </div>
- </div>
- <!-- 70% 영역: 단일 배너 -->
- <div class="swiper--banner--section">
- <div class="swiper--container" ref="swiperContainer">
- <div class="swiper-wrapper">
- <div v-for="(slide, index) in slides" :key="index" class="swiper-slide">
- <div class="slide--image">
- <img
- :src="slide.image"
- :alt="slide.alt || 'Banner Image'"
- loading="lazy"
- />
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
- </template>
- <script setup>
- import { Swiper } from "swiper";
- import { Navigation, Pagination, Autoplay } from "swiper/modules";
- import "swiper/css";
- import "swiper/css/navigation";
- import "swiper/css/pagination";
- // Props 정의
- const props = defineProps({
- slides: {
- type: Array,
- default: () => [
- {
- image: "/img/exclusive/banner1.jpg",
- alt: "Audi Banner 1",
- title: "Audi R8 V10 Performance",
- subtitle: "순수한 스포츠카의 영혼",
- },
- {
- image: "/img/exclusive/banner2.jpg",
- alt: "Audi Banner 2",
- title: "Audi RS e-tron GT",
- subtitle: "전기차의 미래를 선도하는 GT",
- },
- {
- image: "/img/exclusive/banner3.jpg",
- alt: "Audi Banner 3",
- title: "Audi RS 6 Avant",
- subtitle: "프리미엄 퍼포먼스 왜건의 극치",
- },
- ],
- },
- title: {
- type: String,
- default: "",
- },
- subtitle: {
- type: String,
- default: "",
- },
- smalldesc: {
- type: String,
- default: "",
- },
- morelink: {
- type: String,
- default: "",
- },
- notice: {
- type: String,
- default: "",
- },
- autoplay: {
- type: [Boolean, Object],
- default: () => ({ delay: 5000 }),
- },
- loop: {
- type: Boolean,
- default: true,
- },
- type: {
- type: String,
- default: "horizental", // 'horz' , 'vert'
- validator: (value) => ["horizental", "vertical"].includes(value),
- },
- });
- // Refs
- const swiperContainer = ref(null);
- const paginationRef = ref(null);
- const prevRef = ref(null);
- const nextRef = ref(null);
- const textSlider = ref(null);
- let swiperInstance = null;
- // 현재 슬라이드 인덱스
- const currentSlide = ref(0);
- // 슬라이드별 텍스트 반환 함수들
- const getSlideTitle = (index) => {
- return props.slides[index]?.title || props.title;
- };
- const getSlideSubtitle = (index) => {
- return props.slides[index]?.subtitle || props.subtitle;
- };
- const getSlideSmalldesc = (index) => {
- return props.slides[index]?.smalldesc || props.smalldesc;
- };
- const getSlideMorelink = (index) => {
- return props.slides[index]?.morelink || props.morelink;
- };
- onMounted(() => {
- // Swiper 인스턴스 초기화
- swiperInstance = new Swiper(swiperContainer.value, {
- modules: [Navigation, Pagination, Autoplay],
- slidesPerView: 1,
- spaceBetween: 0,
- loop: props.loop,
- autoplay: props.autoplay
- ? {
- delay:
- typeof props.autoplay === "object" ? props.autoplay.delay || 5000 : 5000,
- disableOnInteraction: false,
- }
- : false,
- navigation: {
- nextEl: nextRef.value,
- prevEl: prevRef.value,
- },
- pagination: {
- el: paginationRef.value,
- clickable: true,
- type: "bullets",
- renderBullet: function (index, className) {
- return '<span class="' + className + '">' + (index + 1) + "</span>";
- },
- },
- effect: "fade",
- fadeEffect: {
- crossFade: true,
- },
- speed: 800,
- // 슬라이드 변경 이벤트
- on: {
- slideChange: function () {
- if (this && this.realIndex !== undefined) {
- currentSlide.value = this.realIndex;
- }
- },
- init: function () {
- if (this && this.realIndex !== undefined) {
- currentSlide.value = this.realIndex;
- }
- },
- },
- });
- });
- onUnmounted(() => {
- if (swiperInstance) {
- swiperInstance.destroy(true, true);
- }
- });
- </script>
|