| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- <template>
- <section
- class="title--visual"
- :data-type="type"
- :data-theme="theme"
- ref="titleVisualRef"
- >
- <div class="title--visual--wrapper">
- <div
- class="title--visual--content"
- :data-align="textAlign"
- :data-animated="animation"
- :class="{ visible: isVisible }"
- >
- <h2 class="title--main">{{ title }}</h2>
- <span class="title--description" v-html="description"></span>
- <div v-if="$slots.default" class="title--additional">
- <slot></slot>
- </div>
- </div>
- </div>
- </section>
- </template>
- <script setup>
- // Props 정의
- const props = defineProps({
- title: {
- type: String,
- required: true,
- default: "특별함을 창조하다",
- },
- description: {
- type: String,
- required: true,
- default:
- "아우디 RS e-tron GT, 아우디 RS 6 Avant, 아우디 RS Q8의 예에서 여러 옵션을 결합하여 Audi exclusive order의 다양성과 개인 맞춤 구성 옵션을 경험해 보세요. 3D 버튼을 클릭하여 3D 보기를 활성화하면 인터랙티브 경험을 할 수 있습니다.",
- },
- textAlign: {
- type: String,
- default: "center", // 'left', 'center', 'right'
- validator: (value) => ["left", "center", "right"].includes(value),
- },
- theme: {
- type: String,
- default: "light", // 'light', 'dark'
- validator: (value) => ["light", "dark"].includes(value),
- },
- type: {
- type: String,
- default: "", // 'light', 'dark'
- validator: (value) => ["", "middle"].includes(value),
- },
- animation: {
- type: Boolean,
- default: true,
- },
- animationDelay: {
- type: Number,
- default: 300, // milliseconds
- },
- });
- // 애니메이션 로직
- import { onMounted, ref } from "vue";
- const isVisible = ref(false);
- const titleVisualRef = ref(null);
- onMounted(() => {
- if (props.animation) {
- // IntersectionObserver로 스크롤 애니메이션 구현
- const observer = new IntersectionObserver(
- (entries) => {
- entries.forEach((entry) => {
- if (entry.isIntersecting) {
- setTimeout(() => {
- isVisible.value = true;
- }, props.animationDelay);
- observer.unobserve(entry.target);
- }
- });
- },
- {
- threshold: 0.3, // 30% 보일 때 애니메이션 시작
- }
- );
- // ref를 통해 현재 컴포넌트 요소만 선택
- if (titleVisualRef.value) {
- observer.observe(titleVisualRef.value);
- }
- // cleanup
- return () => {
- if (titleVisualRef.value) {
- observer.unobserve(titleVisualRef.value);
- }
- };
- } else {
- isVisible.value = true;
- }
- });
- </script>
|