| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- <template>
- <section class="swiper--banner--wrapper3" :data-type="type" :data-fit="fit">
- <div class="top--text--wrap">
- <h2 v-html="mtitle"></h2>
- <div class="mt--40" v-html="stitle"></div>
- </div>
- <div class="swiper--banner--container">
- <!-- 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" v-if="slide.image">
- <img
- :src="slide.image"
- :alt="slide.alt || 'Banner Image'"
- loading="lazy"
- />
- <div class="desc--wrapper">
- <div class="desc--wrap">
- <div class="btn--actions">
- <div class="swiper-button-prev" ref="prevRef">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- width="24"
- height="24"
- viewBox="0 0 24 24"
- fill="none"
- >
- <path
- d="M15 18L9 12L15 6"
- stroke="black"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- />
- </svg>
- </div>
- <div class="swiper-button-next" ref="nextRef">
- <svg
- xmlns="http://www.w3.org/2000/svg"
- width="24"
- height="24"
- viewBox="0 0 24 24"
- fill="none"
- >
- <path
- d="M9 18L15 12L9 6"
- stroke="black"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- />
- </svg>
- </div>
- </div>
- <h2 v-if="getSlideTitle(index)" class="main--title">
- {{ getSlideTitle(index) }}
- </h2>
- <h4
- v-if="getSlideSmalldesc(index)"
- class="desc--title"
- v-html="getSlideSmalldesc(index)"
- ></h4>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
- </template>
- <script setup>
- import { Swiper } from "swiper";
- import { Navigation, Pagination, Autoplay, EffectFade } from "swiper/modules";
- import "swiper/css";
- import "swiper/css/navigation";
- import "swiper/css/pagination";
- import "swiper/css/effect-fade";
- const { getMediaUrl } = useImage();
- // Props 정의
- const props = defineProps({
- slides: {
- type: Array,
- default: () => [],
- },
- height: {
- type: String,
- default: "60%",
- },
- mtitle: {
- type: String,
- default: "",
- },
- stitle: {
- type: String,
- default: "",
- },
- title: {
- type: String,
- default: "",
- },
- subtitle: {
- type: String,
- default: "",
- },
- smalldesc: {
- type: String,
- default: "",
- },
- cautiondesc: {
- type: String,
- default: "",
- },
- morelink: {
- type: String,
- default: "",
- },
- morelinktitle: {
- type: String,
- default: "자세히 보기",
- },
- morelinktarget: {
- type: String,
- default: "_self",
- },
- 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),
- },
- fit: {
- type: String,
- default: "cover",
- validator: (value) => ["cover", "contain"].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;
- };
- const getSlideMorelinktitle = (index) => {
- return props.slides[index]?.morelinktitle || props.morelinktitle;
- };
- const getSlideTarget = (index) => {
- return props.slides[index]?.morelinktarget || props.morelinktarget;
- };
- const getSlideCautiondesc = (index) => {
- return props.slides[index]?.cautiondesc || props.cautiondesc;
- };
- 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,
- pauseOnMouseEnter: true,
- }
- : 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;
- }
- // 모든 비디오 일시정지
- const allVideos = this.el.querySelectorAll("video");
- allVideos.forEach((video) => {
- video.pause();
- video.currentTime = 0;
- });
- // 현재 슬라이드의 비디오 재생
- const currentSlideEl = this.slides[this.activeIndex];
- if (currentSlideEl) {
- const video = currentSlideEl.querySelector("video");
- if (video) {
- video.play().catch((err) => console.log("Video play failed:", err));
- }
- }
- },
- init: function () {
- if (this && this.realIndex !== undefined) {
- currentSlide.value = this.realIndex;
- }
- // 초기 슬라이드의 비디오 재생
- const currentSlideEl = this.slides[this.activeIndex];
- if (currentSlideEl) {
- const video = currentSlideEl.querySelector("video");
- if (video) {
- video.play().catch((err) => console.log("Video play failed:", err));
- }
- }
- },
- },
- });
- });
- onUnmounted(() => {
- if (swiperInstance) {
- swiperInstance.destroy(true, true);
- }
- });
- </script>
|