350 lines
11 KiB
JavaScript
350 lines
11 KiB
JavaScript
// Voyage Layout JavaScript - Smooth, Interactive, Engaging
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Theme is now gold by default - no switcher needed
|
|
|
|
// Navigation scroll effect and logo switching
|
|
const nav = document.getElementById('voyageNav');
|
|
const navLogo = document.getElementById('navLogo');
|
|
const navBrandText = document.querySelector('.nav-brand span');
|
|
let lastScroll = 0;
|
|
|
|
// Set initial logo state
|
|
if (navLogo) {
|
|
navLogo.src = 'HARBOR-SMITH-white.png';
|
|
}
|
|
|
|
window.addEventListener('scroll', () => {
|
|
const currentScroll = window.pageYOffset;
|
|
|
|
if (currentScroll > 50) {
|
|
nav.classList.add('scrolled');
|
|
// Switch to navy logo when scrolled (white background)
|
|
if (navLogo) {
|
|
navLogo.src = 'HARBOR-SMITH_navy.png';
|
|
navLogo.alt = 'Harbor Smith Navy Logo';
|
|
}
|
|
// Also change text color to match
|
|
if (navBrandText) {
|
|
navBrandText.style.color = '#1e3a5f';
|
|
}
|
|
} else {
|
|
nav.classList.remove('scrolled');
|
|
// Switch to white logo when at top (over video)
|
|
if (navLogo) {
|
|
navLogo.src = 'HARBOR-SMITH-white.png';
|
|
navLogo.alt = 'Harbor Smith White Logo';
|
|
}
|
|
// Reset text color to white
|
|
if (navBrandText) {
|
|
navBrandText.style.color = 'white';
|
|
}
|
|
}
|
|
|
|
lastScroll = currentScroll;
|
|
});
|
|
|
|
// Smooth scroll for navigation links
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
const target = document.querySelector(this.getAttribute('href'));
|
|
if (target) {
|
|
target.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'start'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Parallax effect for hero video
|
|
const heroSection = document.getElementById('heroSection');
|
|
const heroVideo = document.querySelector('.hero-video-container');
|
|
|
|
window.addEventListener('scroll', () => {
|
|
const scrolled = window.pageYOffset;
|
|
const rate = scrolled * 0.5;
|
|
|
|
if (heroVideo) {
|
|
heroVideo.style.transform = `translateY(${rate}px)`;
|
|
}
|
|
});
|
|
|
|
// Fleet Carousel
|
|
const yachtCards = document.querySelectorAll('.yacht-card');
|
|
const dots = document.querySelectorAll('.dot');
|
|
const prevBtn = document.querySelector('.fleet-prev');
|
|
const nextBtn = document.querySelector('.fleet-next');
|
|
let currentYacht = 0;
|
|
|
|
function showYacht(index) {
|
|
yachtCards.forEach(card => card.classList.remove('active'));
|
|
dots.forEach(dot => dot.classList.remove('active'));
|
|
|
|
yachtCards[index].classList.add('active');
|
|
dots[index].classList.add('active');
|
|
}
|
|
|
|
if (prevBtn && nextBtn) {
|
|
prevBtn.addEventListener('click', () => {
|
|
currentYacht = (currentYacht - 1 + yachtCards.length) % yachtCards.length;
|
|
showYacht(currentYacht);
|
|
});
|
|
|
|
nextBtn.addEventListener('click', () => {
|
|
currentYacht = (currentYacht + 1) % yachtCards.length;
|
|
showYacht(currentYacht);
|
|
});
|
|
}
|
|
|
|
dots.forEach((dot, index) => {
|
|
dot.addEventListener('click', () => {
|
|
currentYacht = index;
|
|
showYacht(currentYacht);
|
|
});
|
|
});
|
|
|
|
// Auto-rotate fleet carousel
|
|
setInterval(() => {
|
|
if (document.visibilityState === 'visible') {
|
|
currentYacht = (currentYacht + 1) % yachtCards.length;
|
|
showYacht(currentYacht);
|
|
}
|
|
}, 5000);
|
|
|
|
// CTA Button interactions
|
|
document.querySelectorAll('.btn-primary-warm, .btn-secondary-warm').forEach(btn => {
|
|
btn.addEventListener('click', function(e) {
|
|
// Create ripple effect
|
|
const ripple = document.createElement('span');
|
|
ripple.classList.add('ripple');
|
|
this.appendChild(ripple);
|
|
|
|
const rect = this.getBoundingClientRect();
|
|
const size = Math.max(rect.width, rect.height);
|
|
const x = e.clientX - rect.left - size / 2;
|
|
const y = e.clientY - rect.top - size / 2;
|
|
|
|
ripple.style.width = ripple.style.height = size + 'px';
|
|
ripple.style.left = x + 'px';
|
|
ripple.style.top = y + 'px';
|
|
|
|
setTimeout(() => ripple.remove(), 600);
|
|
});
|
|
});
|
|
|
|
// Add ripple styles
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
.ripple {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
background: rgba(255, 255, 255, 0.6);
|
|
transform: scale(0);
|
|
animation: ripple 0.6s ease-out;
|
|
pointer-events: none;
|
|
}
|
|
|
|
@keyframes ripple {
|
|
to {
|
|
transform: scale(4);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
.btn-primary-warm,
|
|
.btn-secondary-warm {
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
|
|
// Animate elements on scroll
|
|
const observerOptions = {
|
|
threshold: 0.1,
|
|
rootMargin: '0px 0px -100px 0px'
|
|
};
|
|
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.style.opacity = '1';
|
|
entry.target.style.transform = 'translateY(0)';
|
|
}
|
|
});
|
|
}, observerOptions);
|
|
|
|
// Observe elements for animation
|
|
document.querySelectorAll('.welcome-content, .story-card, .booking-card').forEach(el => {
|
|
el.style.opacity = '0';
|
|
el.style.transform = 'translateY(30px)';
|
|
el.style.transition = 'all 0.6s ease';
|
|
observer.observe(el);
|
|
});
|
|
|
|
// Interactive booking cards
|
|
document.querySelectorAll('.booking-card').forEach(card => {
|
|
card.addEventListener('mouseenter', function() {
|
|
this.style.transform = 'translateY(-10px) scale(1.02)';
|
|
});
|
|
|
|
card.addEventListener('mouseleave', function() {
|
|
if (this.classList.contains('featured')) {
|
|
this.style.transform = 'scale(1.05)';
|
|
} else {
|
|
this.style.transform = 'translateY(0) scale(1)';
|
|
}
|
|
});
|
|
});
|
|
|
|
// Phone number click handler
|
|
document.querySelectorAll('.btn-booking.primary').forEach(btn => {
|
|
if (btn.textContent.includes('415')) {
|
|
btn.addEventListener('click', () => {
|
|
window.location.href = 'tel:4155550123';
|
|
});
|
|
}
|
|
});
|
|
|
|
// Video optimization - pause when not visible
|
|
const video = document.querySelector('.hero-video');
|
|
if (video) {
|
|
const videoObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
video.play();
|
|
} else {
|
|
video.pause();
|
|
}
|
|
});
|
|
}, { threshold: 0.25 });
|
|
|
|
videoObserver.observe(video);
|
|
}
|
|
|
|
// Story cards hover effect
|
|
document.querySelectorAll('.story-card').forEach(card => {
|
|
const img = card.querySelector('img');
|
|
|
|
card.addEventListener('mouseenter', () => {
|
|
if (img) {
|
|
img.style.transform = 'scale(1.1)';
|
|
img.style.transition = 'transform 0.6s ease';
|
|
}
|
|
});
|
|
|
|
card.addEventListener('mouseleave', () => {
|
|
if (img) {
|
|
img.style.transform = 'scale(1)';
|
|
}
|
|
});
|
|
});
|
|
|
|
// Dynamic trust badge counter - starts from 0
|
|
// Target the white text span specifically (the second span in trust-badge)
|
|
const trustBadge = document.querySelector('.trust-badge > span:last-child');
|
|
if (trustBadge) {
|
|
let count = 0;
|
|
const targetCount = 100;
|
|
const duration = 2000; // 2 seconds
|
|
const steps = 50;
|
|
const increment = targetCount / steps;
|
|
const stepDuration = duration / steps;
|
|
|
|
// Start with 0
|
|
trustBadge.textContent = `Trusted by 0+ seafarers`;
|
|
|
|
const counter = setInterval(() => {
|
|
count += increment;
|
|
if (count >= targetCount) {
|
|
count = targetCount;
|
|
clearInterval(counter);
|
|
trustBadge.textContent = `Trusted by 100+ seafarers`;
|
|
} else {
|
|
trustBadge.textContent = `Trusted by ${Math.floor(count)}+ seafarers`;
|
|
}
|
|
}, stepDuration);
|
|
}
|
|
|
|
// Remove any duplicate red text that might exist
|
|
const allSpans = document.querySelectorAll('.hero-content span');
|
|
allSpans.forEach(span => {
|
|
// Check if this is the red duplicate text (not inside trust-badge)
|
|
if (span.textContent.includes('Trusted by') &&
|
|
span.textContent.includes('adventurers') &&
|
|
!span.closest('.trust-badge')) {
|
|
span.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
// Smooth hover for navigation links
|
|
document.querySelectorAll('.nav-link').forEach(link => {
|
|
link.addEventListener('mouseenter', function() {
|
|
this.style.transform = 'translateY(-2px)';
|
|
});
|
|
|
|
link.addEventListener('mouseleave', function() {
|
|
this.style.transform = 'translateY(0)';
|
|
});
|
|
});
|
|
|
|
// Mobile menu (would need to add hamburger menu for production)
|
|
const mobileMenuBtn = document.createElement('button');
|
|
mobileMenuBtn.className = 'mobile-menu-btn';
|
|
mobileMenuBtn.innerHTML = '<span></span><span></span><span></span>';
|
|
mobileMenuBtn.style.cssText = `
|
|
display: none;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
background: transparent;
|
|
border: none;
|
|
cursor: pointer;
|
|
padding: 0.5rem;
|
|
`;
|
|
|
|
// Add mobile menu styles
|
|
const mobileStyles = document.createElement('style');
|
|
mobileStyles.textContent = `
|
|
@media (max-width: 768px) {
|
|
.mobile-menu-btn {
|
|
display: flex !important;
|
|
}
|
|
|
|
.mobile-menu-btn span {
|
|
width: 24px;
|
|
height: 2px;
|
|
background: white;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.voyage-nav.scrolled .mobile-menu-btn span {
|
|
background: var(--primary-blue);
|
|
}
|
|
}
|
|
`;
|
|
document.head.appendChild(mobileStyles);
|
|
|
|
// Add mobile menu button to nav
|
|
const navContainer = document.querySelector('.nav-container');
|
|
if (navContainer && window.innerWidth <= 768) {
|
|
navContainer.appendChild(mobileMenuBtn);
|
|
}
|
|
|
|
// Loading animation for images
|
|
document.querySelectorAll('img').forEach(img => {
|
|
// Check if image is already loaded
|
|
if (img.complete && img.naturalHeight !== 0) {
|
|
img.style.opacity = '1';
|
|
} else {
|
|
img.style.opacity = '0';
|
|
img.addEventListener('load', function() {
|
|
this.style.opacity = '1';
|
|
});
|
|
}
|
|
img.style.transition = 'opacity 0.6s ease';
|
|
});
|
|
|
|
console.log('Voyage layout initialized successfully!');
|
|
}); |