-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
226 lines (190 loc) · 8.39 KB
/
Copy pathscript.js
File metadata and controls
226 lines (190 loc) · 8.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/* -------------------------------------------------------------
* Christian Dior Perfume Collection Interactive Script
* Features: Buttery-smooth Scroll Parallax Zoom, Intersection Observer
* Reveals, Responsive Mobile Overlays, and 3D Floating Olfactive Notes.
* Developed by: Top-Tier Lead Frontend Architect & Interactive Web Designer
* ------------------------------------------------------------- */
document.addEventListener('DOMContentLoaded', () => {
// ==========================================
// 1. Sticky Header & Glassmorphic Transition
// ==========================================
const header = document.getElementById('main-header');
const handleScrollHeader = () => {
if (window.scrollY > 50) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
};
window.addEventListener('scroll', handleScrollHeader, { passive: true });
handleScrollHeader(); // Trigger initially
// ==========================================
// 2. Mobile Hamburger Toggle Menu
// ==========================================
const hamburgerToggle = document.getElementById('hamburgerToggle');
const mobileNav = document.getElementById('mobileNav');
const mobileNavLinks = document.querySelectorAll('.mobile-nav-item');
const toggleMobileMenu = () => {
hamburgerToggle.classList.toggle('active');
mobileNav.classList.toggle('active');
// Toggle body scrolling lock
if (mobileNav.classList.contains('active')) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
};
hamburgerToggle.addEventListener('click', toggleMobileMenu);
// Close mobile nav when clicking any nav item
mobileNavLinks.forEach(link => {
link.addEventListener('click', () => {
hamburgerToggle.classList.remove('active');
mobileNav.classList.remove('active');
document.body.style.overflow = '';
});
});
// ==========================================
// 3. Scroll Reveal Animations (Intersection Observer)
// ==========================================
const revealElements = document.querySelectorAll('.scroll-reveal, .left-slide, .right-slide');
const revealOptions = {
threshold: 0.12,
rootMargin: '0px 0px -40px 0px'
};
const revealObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target); // Reveal once
}
});
}, revealOptions);
revealElements.forEach(element => {
revealObserver.observe(element);
});
// ==========================================
// 4. Olfactive Parallax Scroll Zoom & Floating Notes
// ==========================================
const experienceSection = document.getElementById('experience');
const experienceBgImg = document.getElementById('experienceBgImg');
const experienceBottle = document.getElementById('experienceBottle');
const experienceCards = document.querySelectorAll('.experience-card');
const floatingNotes = document.querySelectorAll('.floating-note');
let tick = false;
const handleOlfactiveParallax = () => {
if (!experienceSection) return;
const sectionRect = experienceSection.getBoundingClientRect();
const sectionHeight = experienceSection.offsetHeight;
const viewportHeight = window.innerHeight;
// Check if the experience section is currently inside the viewport area
if (sectionRect.top <= 0 && sectionRect.bottom >= viewportHeight) {
// Calculate scroll progress percentage (from 0.0 to 1.0)
const scrolledInSection = Math.abs(sectionRect.top);
const totalScrollableDistance = sectionHeight - viewportHeight;
const progress = Math.min(Math.max(scrolledInSection / totalScrollableDistance, 0), 1);
// 1. Zoom and rotate the Dior perfume bottle visual
const minScale = 0.9;
const maxScale = 1.6;
const currentScale = minScale + (progress * (maxScale - minScale));
const rotation = progress * 15; // Subtle 15-degree rotate
if (experienceBottle) {
experienceBottle.style.transform = `scale(${currentScale}) rotate(${rotation}deg)`;
}
// 2. Parallax effect for the background gold silk / crystal textures
if (experienceBgImg) {
const bgTranslate = -progress * 40; // Shift background slightly up
const bgScale = 1.05 + (progress * 0.05);
experienceBgImg.style.transform = `scale(${bgScale}) translateY(${bgTranslate}px)`;
}
// 3. Staggered 3D expansion of olfactory note tags
// Expand outer vectors from the bottle as it zooms closer
const noteTranslations = [
{ x: -90, y: -50 }, // Calabrian Bergamot
{ x: 110, y: -70 }, // Damascus Rose
{ x: -100, y: 50 }, // Grasse Jasmine
{ x: 90, y: 70 }, // White Musk
{ x: -40, y: 110 } // Atlas Cedarwood
];
floatingNotes.forEach((note, index) => {
const trans = noteTranslations[index] || { x: 0, y: 0 };
const currentX = progress * trans.x;
const currentY = progress * trans.y;
// Fade in as scrolling progresses, then fade out near completion to clear screen
let opacity = 0.3 + (progress * 0.7);
if (progress > 0.85) {
opacity = (1 - progress) * 6.6; // Quick fade out at extreme end
}
note.style.transform = `translate(${currentX}px, ${currentY}px)`;
note.style.opacity = Math.max(0, Math.min(1, opacity));
});
// 4. Stagger active text description cards based on scroll depth
if (progress < 0.33) {
updateActiveCard(0);
} else if (progress >= 0.33 && progress < 0.66) {
updateActiveCard(1);
} else {
updateActiveCard(2);
}
} else if (sectionRect.top > 0) {
// Baseline State: Scroll position is before entering the section
if (experienceBottle) {
experienceBottle.style.transform = 'scale(0.9) rotate(0deg)';
}
if (experienceBgImg) {
experienceBgImg.style.transform = 'scale(1.05) translateY(0px)';
}
floatingNotes.forEach(note => {
note.style.transform = 'translate(0px, 0px)';
note.style.opacity = '0.3';
});
updateActiveCard(0);
} else if (sectionRect.bottom < viewportHeight) {
// Fully Scrolled Past State: Keep maximum scale and end animations
if (experienceBottle) {
experienceBottle.style.transform = 'scale(1.6) rotate(15deg)';
}
if (experienceBgImg) {
experienceBgImg.style.transform = 'scale(1.1) translateY(-40px)';
}
floatingNotes.forEach((note, index) => {
const trans = noteTranslations[index] || { x: 0, y: 0 };
note.style.transform = `translate(${trans.x}px, ${trans.y}px)`;
note.style.opacity = '0';
});
updateActiveCard(2);
}
};
const updateActiveCard = (index) => {
experienceCards.forEach((card, i) => {
if (i === index) {
card.classList.add('active');
} else {
card.classList.remove('active');
}
});
};
window.addEventListener('scroll', () => {
if (!tick) {
window.requestAnimationFrame(() => {
handleOlfactiveParallax();
tick = false;
});
tick = true;
}
}, { passive: true });
// ==========================================
// 5. Luxury Order Consultation Form Submission
// ==========================================
const orderForm = document.getElementById('luxuryOrderForm');
if (orderForm) {
orderForm.addEventListener('submit', (e) => {
e.preventDefault();
const clientName = document.getElementById('userName').value;
const perfumeSelect = document.getElementById('modelSelect');
const selectedPerfume = perfumeSelect.options[perfumeSelect.selectedIndex].text;
// Show high-end stylized congratulations alert
alert(`DIOR BOUTIQUE\n-------------------------\n친애하는 ${clientName} 귀하,\n\n디올 시그니처 컬렉션 [${selectedPerfume}] 런칭 혜택 신청이 안전하게 접수되었습니다.\n\n디올 전문 부티크 상담원이 영업시간 기준 1시간 이내에 입력하신 연락처로 전용 서비스 안내를 위해 연락드릴 예정입니다.\n\n크리스찬 디올의 감성을 고스란히 담은 예술적인 언박싱의 설렘을 곧 선사하겠습니다.\n감사합니다.`);
orderForm.reset();
});
}
});