726 lines
25 KiB
Plaintext
726 lines
25 KiB
Plaintext
<div class="relative py-16 md:py-32 bg-gradient-to-b from-slate-50 to-slate-100 overflow-hidden">
|
|
<!-- Background subtle design elements -->
|
|
<div class="absolute top-0 left-0 w-full h-full overflow-hidden">
|
|
<div class="absolute top-0 left-0 w-full h-full bg-grid-pattern opacity-5"></div>
|
|
<div class="absolute top-10 left-10 w-32 h-32 bg-blue-500 rounded-full filter blur-[100px] opacity-20"></div>
|
|
<div class="absolute bottom-10 right-10 w-32 h-32 bg-purple-500 rounded-full filter blur-[100px] opacity-20"></div>
|
|
<div id="particle-container" class="absolute inset-0"></div>
|
|
</div>
|
|
|
|
<div class="container mx-auto px-4 max-w-5xl relative z-10">
|
|
<!-- Heading Section with animated underline -->
|
|
<div class="text-center">
|
|
<div class="inline-block relative">
|
|
<h2 class="text-2xl md:text-3xl font-bold text-gray-800">
|
|
Layanan Digital
|
|
</h2>
|
|
@* <div class="heading-underline"></div> *@
|
|
</div>
|
|
<p class="max-w-2xl mx-auto text-lg md:text-xl leading-relaxed text-gray-600 mt-6">
|
|
Solusi digital inovatif dari DLH DKI Jakarta untuk Jakarta yang lebih bersih,
|
|
hijau, dan berkelanjutan.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- 3D Website Showcase -->
|
|
<div id="websites-showcase" class="relative">
|
|
<!-- Laptop mockup container -->
|
|
<div class="laptop-viewport relative max-w-3xl mx-auto h-[300px] md:h-[600px]">
|
|
<div class="laptop-container w-full h-full relative transform-gpu perspective">
|
|
<!-- Website slides will be created by JavaScript within this laptop mockup -->
|
|
</div>
|
|
|
|
<!-- Floating UI elements -->
|
|
@* <div class="floating-ui-element device-metrics absolute top-0 left-0 md:left-10 p-4 bg-white/10 backdrop-blur-lg rounded-lg border border-white/30 shadow-xl transform-gpu -translate-y-1/2 opacity-0">
|
|
<div class="flex items-center gap-2">
|
|
<span class="w-3 h-3 rounded-full bg-red-500"></span>
|
|
<div>
|
|
<span class="text-xs font-mono text-gray-700 block">Resolution</span>
|
|
<span class="text-sm font-bold text-gray-900">1920 x 1080</span>
|
|
</div>
|
|
</div>
|
|
</div> *@
|
|
|
|
<div class="floating-ui-element website-info absolute top-10 right-0 md:right-10 p-4 bg-white/10 backdrop-blur-lg rounded-lg border border-white/30 shadow-xl transform-gpu translate-y-1/2 opacity-0">
|
|
<h3 class="text-lg font-bold text-gray-900" id="current-website-title">Sistem Ketaatan Lingkungan</h3>
|
|
<div class="flex items-center mt-2">
|
|
<div class="flex items-center bg-gray-100 rounded-l-md px-3 py-2">
|
|
<span class="text-gray-500">https://</span>
|
|
</div>
|
|
<input type="text" id="urlDisplay" value="wasdal.jakarta.go.id" class="bg-white py-2 px-3 border-y border-r border-gray-200 rounded-r-md text-gray-800 text-sm flex-1 font-medium focus:outline-none" readonly>
|
|
</div>
|
|
<div class="mt-2 flex justify-end">
|
|
<a href="#" id="visitWebsite" target="_blank" class="visit-btn inline-flex items-center gap-1 px-3 py-1 rounded-md text-white text-sm font-medium">
|
|
<span>Kunjungi</span>
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Custom navigation -->
|
|
<div class="website-nav flex items-center justify-center">
|
|
<button id="prev-website" class="nav-btn flex items-center justify-center w-12 h-12 rounded-full bg-white/80 backdrop-blur-sm shadow-lg hover:bg-white transition-all duration-300 focus:outline-none">
|
|
<svg class="w-5 h-5 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<div class="website-progress relative h-1 bg-gray-200 rounded-full mx-6 overflow-hidden w-1/3 max-w-xs">
|
|
<div class="absolute top-0 left-0 h-full bg-gradient-to-r from-green-500 to-green-600 rounded-full progress-bar" style="width: 0%"></div>
|
|
</div>
|
|
|
|
<div id="website-indicators" class="hidden md:flex justify-center space-x-3 mx-6">
|
|
<!-- Indicators will be dynamically populated -->
|
|
</div>
|
|
|
|
<button id="next-website" class="nav-btn flex items-center justify-center w-12 h-12 rounded-full bg-white/80 backdrop-blur-sm shadow-lg hover:bg-white transition-all duration-300 focus:outline-none">
|
|
<svg class="w-5 h-5 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Visual tech elements -->
|
|
@* <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-12 max-w-4xl mx-auto">
|
|
<div class="tech-feature bg-white rounded-xl p-4 shadow-lg transform hover:-translate-y-1 transition-all duration-300">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-blue-50 rounded-lg">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<span class="text-sm font-medium text-gray-800">Aman</span>
|
|
<span class="block text-xs text-gray-500">SSL Secured</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tech-feature bg-white rounded-xl p-4 shadow-lg transform hover:-translate-y-1 transition-all duration-300">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-green-50 rounded-lg">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<span class="text-sm font-medium text-gray-800">Cepat</span>
|
|
<span class="block text-xs text-gray-500">Optimized</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tech-feature bg-white rounded-xl p-4 shadow-lg transform hover:-translate-y-1 transition-all duration-300">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-purple-50 rounded-lg">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-purple-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<span class="text-sm font-medium text-gray-800">Responsif</span>
|
|
<span class="block text-xs text-gray-500">Mobile-friendly</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tech-feature bg-white rounded-xl p-4 shadow-lg transform hover:-translate-y-1 transition-all duration-300">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-amber-50 rounded-lg">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-amber-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<span class="text-sm font-medium text-gray-800">Terintegrasi</span>
|
|
<span class="block text-xs text-gray-500">Connected APIs</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> *@
|
|
</div>
|
|
</div>
|
|
|
|
<register-block dynamic-section="css" key="cssWebsite">
|
|
<style>
|
|
/* Background pattern */
|
|
.bg-grid-pattern {
|
|
background-image: radial-gradient(circle, #000 1px, transparent 1px);
|
|
background-size: 30px 30px;
|
|
}
|
|
|
|
/* Animated heading underline */
|
|
.heading-underline {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
height: 4px;
|
|
width: 0;
|
|
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
|
|
border-radius: 4px;
|
|
animation: underline-expand 1.5s ease-out forwards;
|
|
}
|
|
|
|
@@keyframes underline-expand {
|
|
0% { width: 0; }
|
|
100% { width: 100%; }
|
|
}
|
|
|
|
/* 3D perspective for laptop */
|
|
.perspective {
|
|
perspective: 2500px;
|
|
transform-style: preserve-3d;
|
|
}
|
|
|
|
/* Laptop mockup styles */
|
|
.laptop-mockup {
|
|
position: absolute;
|
|
width: 80%;
|
|
height: 70%;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%) rotateX(20deg);
|
|
transform-style: preserve-3d;
|
|
transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
}
|
|
|
|
.laptop-lid {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: #32363e;
|
|
border-radius: 12px;
|
|
padding: 8px;
|
|
}
|
|
|
|
.laptop-screen {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: #000;
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.laptop-keyboard {
|
|
position: absolute;
|
|
width: 110%;
|
|
height: 10px;
|
|
bottom: -15px;
|
|
left: -5%;
|
|
background: linear-gradient(to bottom, #32363e, #1a1c20);
|
|
border-bottom-left-radius: 10px;
|
|
border-bottom-right-radius: 10px;
|
|
transform: rotateX(-90deg);
|
|
transform-origin: top;
|
|
transform-style: preserve-3d;
|
|
box-shadow: 0 6px 20px rgba(0,0,0,0.2);
|
|
}
|
|
|
|
.laptop-keyboard::after {
|
|
content: '';
|
|
position: absolute;
|
|
width: 20%;
|
|
height: 4px;
|
|
bottom: 3px;
|
|
left: 40%;
|
|
background: #555;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.laptop-camera {
|
|
position: absolute;
|
|
top: 6px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: #333;
|
|
z-index: 10;
|
|
}
|
|
|
|
/* Website slide styles */
|
|
.website-slide {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
opacity: 0;
|
|
transform: translateZ(-500px);
|
|
transition: all 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
}
|
|
|
|
.website-slide.active {
|
|
opacity: 1;
|
|
transform: translateZ(0);
|
|
}
|
|
|
|
.website-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
/* Floating UI elements */
|
|
.floating-ui-element {
|
|
transition: all 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
}
|
|
|
|
/* Visit button styling */
|
|
.visit-btn {
|
|
background-color: #f49827;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.visit-btn:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
|
|
}
|
|
|
|
/* Navigation button effects */
|
|
.nav-btn {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.nav-btn:hover {
|
|
transform: scale(1.05);
|
|
}
|
|
|
|
.nav-btn:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
/* Progress bar animation */
|
|
.progress-bar {
|
|
transition: width 0.3s ease-in-out;
|
|
}
|
|
|
|
/* Indicator styling */
|
|
.website-indicator {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: rgba(34, 197, 94, 0.3);
|
|
transition: all 0.3s ease;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.website-indicator.active {
|
|
background: #26ac7e;
|
|
transform: scale(1.2);
|
|
}
|
|
|
|
/* Tech feature hover */
|
|
.tech-feature {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
/* Particle styling */
|
|
.website-particle {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
background-color: rgba(79, 70, 229, 0.2);
|
|
pointer-events: none;
|
|
}
|
|
</style>
|
|
</register-block>
|
|
|
|
<register-block dynamic-section="scripts" key="jsWebsite">
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
const asset = (file) => `${window.assetBaseUrl}images/home/${file}`;
|
|
|
|
// Website data configuration
|
|
const websites = [
|
|
{
|
|
image: asset("skl.jpg"),
|
|
url: "wasdal.jakarta.go.id",
|
|
title: "Sistem Ketaatan Lingkungan",
|
|
color: "#3b82f6"
|
|
},
|
|
{
|
|
image: asset("bps.jpg"),
|
|
url: "jaklingko.jakarta.go.id",
|
|
title: "Jakarta Lingko",
|
|
color: "#10b981"
|
|
},
|
|
{
|
|
image: asset("skl.jpg"),
|
|
url: "lingkungan.jakarta.go.id",
|
|
title: "Lingkungan Jakarta",
|
|
color: "#f59e0b"
|
|
},
|
|
{
|
|
image: asset("bps.jpg"),
|
|
url: "bpsrw.jakarta.go.id",
|
|
title: "Bank Sampah RW",
|
|
color: "#8b5cf6"
|
|
},
|
|
{
|
|
image: asset("skl.jpg"),
|
|
url: "dlhjakarta.go.id",
|
|
title: "Portal DLH Jakarta",
|
|
color: "#ef4444"
|
|
}
|
|
];
|
|
|
|
// DOM Elements
|
|
const laptopContainer = document.querySelector('.laptop-container');
|
|
const indicatorsContainer = document.getElementById('website-indicators');
|
|
const urlDisplay = document.getElementById('urlDisplay');
|
|
const websiteTitle = document.getElementById('current-website-title');
|
|
const visitBtn = document.getElementById('visitWebsite');
|
|
const prevBtn = document.getElementById('prev-website');
|
|
const nextBtn = document.getElementById('next-website');
|
|
const progressBar = document.querySelector('.progress-bar');
|
|
|
|
let currentIndex = 0;
|
|
let isAnimating = false;
|
|
|
|
// Create laptop mockup with websites inside
|
|
const laptopMockup = document.createElement('div');
|
|
laptopMockup.className = 'laptop-mockup';
|
|
laptopMockup.innerHTML = `
|
|
<div class="laptop-lid">
|
|
<div class="laptop-camera"></div>
|
|
<div class="laptop-screen">
|
|
<!-- Website slides will be added here -->
|
|
</div>
|
|
</div>
|
|
<div class="laptop-keyboard"></div>
|
|
`;
|
|
|
|
laptopContainer.appendChild(laptopMockup);
|
|
|
|
const laptopScreen = laptopMockup.querySelector('.laptop-screen');
|
|
|
|
// Create website slides
|
|
websites.forEach((site, index) => {
|
|
// Create slide
|
|
const slide = document.createElement('div');
|
|
slide.className = `website-slide ${index === 0 ? 'active' : ''}`;
|
|
slide.setAttribute('data-index', index);
|
|
|
|
slide.innerHTML = `
|
|
<img src="${site.image}" alt="${site.title}" class="website-image">
|
|
`;
|
|
|
|
laptopScreen.appendChild(slide);
|
|
|
|
// Create indicator
|
|
const indicator = document.createElement('button');
|
|
indicator.className = `website-indicator ${index === 0 ? 'active' : ''}`;
|
|
indicator.setAttribute('data-index', index);
|
|
indicator.addEventListener('click', () => {
|
|
if (!isAnimating && currentIndex !== index) {
|
|
goToSlide(index);
|
|
}
|
|
});
|
|
|
|
indicatorsContainer.appendChild(indicator);
|
|
});
|
|
|
|
const slides = document.querySelectorAll('.website-slide');
|
|
const indicators = document.querySelectorAll('.website-indicator');
|
|
|
|
// Initialize website information
|
|
updateWebsiteInfo(0);
|
|
|
|
// Create floating UI animations
|
|
const floatingElements = document.querySelectorAll('.floating-ui-element');
|
|
floatingElements.forEach((el, index) => {
|
|
// Show elements with stagger
|
|
gsap.to(el, {
|
|
opacity: 1,
|
|
y: 0,
|
|
delay: 0.5 + (index * 0.2),
|
|
duration: 1,
|
|
ease: "power3.out"
|
|
});
|
|
|
|
// Add slight floating animation
|
|
gsap.to(el, {
|
|
y: "+=10",
|
|
duration: 2,
|
|
ease: "sine.inOut",
|
|
repeat: -1,
|
|
yoyo: true,
|
|
delay: Math.random()
|
|
});
|
|
});
|
|
|
|
// Create particles
|
|
createParticles();
|
|
|
|
// Initialize 3D laptop animation
|
|
gsap.fromTo(laptopMockup,
|
|
{
|
|
rotateX: 40,
|
|
rotateY: 10,
|
|
y: 100,
|
|
opacity: 0
|
|
},
|
|
{
|
|
rotateX: 20,
|
|
rotateY: 0,
|
|
y: 0,
|
|
opacity: 1,
|
|
duration: 1.5,
|
|
ease: "power3.out",
|
|
delay: 0.3
|
|
}
|
|
);
|
|
|
|
// Laptop subtle movement based on mouse position
|
|
const websitesShowcase = document.getElementById('websites-showcase');
|
|
websitesShowcase.addEventListener('mousemove', (e) => {
|
|
const rect = websitesShowcase.getBoundingClientRect();
|
|
const mouseX = e.clientX - rect.left - (rect.width / 2);
|
|
const mouseY = e.clientY - rect.top - (rect.height / 2);
|
|
|
|
gsap.to(laptopMockup, {
|
|
rotateY: mouseX * 0.005,
|
|
rotateX: 20 - (mouseY * 0.01),
|
|
duration: 1,
|
|
ease: "power1.out"
|
|
});
|
|
});
|
|
|
|
// Reset rotation when mouse leaves
|
|
websitesShowcase.addEventListener('mouseleave', () => {
|
|
gsap.to(laptopMockup, {
|
|
rotateX: 20,
|
|
rotateY: 0,
|
|
duration: 1,
|
|
ease: "power1.out"
|
|
});
|
|
});
|
|
|
|
// Update website information
|
|
function updateWebsiteInfo(index) {
|
|
const site = websites[index];
|
|
if (!site) return;
|
|
|
|
// Update URL and title
|
|
urlDisplay.value = site.url;
|
|
websiteTitle.textContent = site.title;
|
|
visitBtn.href = `https://${site.url}`;
|
|
|
|
// Update progress bar
|
|
const progress = ((index + 1) / websites.length) * 100;
|
|
progressBar.style.width = `${progress}%`;
|
|
|
|
// Update visit button color
|
|
@* gsap.to(visitBtn, {
|
|
background: `linear-gradient(to right, ${site.color}, ${adjustBrightness(site.color, -20)})`,
|
|
duration: 0.5
|
|
}); *@
|
|
}
|
|
|
|
// Helper function to adjust brightness
|
|
function adjustBrightness(hex, percent) {
|
|
// This is a simplified version
|
|
return hex;
|
|
}
|
|
|
|
// Update slider
|
|
function goToSlide(index) {
|
|
if (isAnimating) return;
|
|
isAnimating = true;
|
|
|
|
// Get current and new slide
|
|
const currentSlide = slides[currentIndex];
|
|
const newSlide = slides[index];
|
|
|
|
// Direction for animation (left or right)
|
|
const direction = index > currentIndex ? 1 : -1;
|
|
|
|
// Update current index
|
|
currentIndex = index;
|
|
|
|
// Animate current slide out
|
|
gsap.to(currentSlide, {
|
|
opacity: 0,
|
|
z: -500 * direction,
|
|
duration: 0.8,
|
|
ease: "power2.in"
|
|
});
|
|
|
|
// Prepare new slide
|
|
gsap.set(newSlide, {
|
|
opacity: 0,
|
|
z: 500 * -direction
|
|
});
|
|
|
|
// Animate new slide in
|
|
gsap.to(newSlide, {
|
|
opacity: 1,
|
|
z: 0,
|
|
duration: 0.8,
|
|
delay: 0.2,
|
|
ease: "power2.out",
|
|
onComplete: () => {
|
|
isAnimating = false;
|
|
|
|
// Update classes
|
|
slides.forEach(slide => slide.classList.remove('active'));
|
|
newSlide.classList.add('active');
|
|
|
|
// Update indicators
|
|
indicators.forEach((indicator, i) => {
|
|
if (i === index) {
|
|
indicator.classList.add('active');
|
|
} else {
|
|
indicator.classList.remove('active');
|
|
}
|
|
});
|
|
|
|
// Update website information
|
|
updateWebsiteInfo(index);
|
|
}
|
|
});
|
|
|
|
// Animate laptop slightly based on direction
|
|
gsap.to(laptopMockup, {
|
|
rotateY: 5 * direction,
|
|
duration: 0.8,
|
|
ease: "power2.inOut",
|
|
onComplete: () => {
|
|
gsap.to(laptopMockup, {
|
|
rotateY: 0,
|
|
duration: 0.6,
|
|
ease: "power2.out"
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Navigation functions
|
|
prevBtn.addEventListener('click', () => {
|
|
if (!isAnimating) {
|
|
const prevIndex = (currentIndex - 1 + websites.length) % websites.length;
|
|
goToSlide(prevIndex);
|
|
}
|
|
});
|
|
|
|
nextBtn.addEventListener('click', () => {
|
|
if (!isAnimating) {
|
|
const nextIndex = (currentIndex + 1) % websites.length;
|
|
goToSlide(nextIndex);
|
|
}
|
|
});
|
|
|
|
// Create and animate particles
|
|
function createParticles() {
|
|
const particleContainer = document.getElementById('particle-container');
|
|
const particleCount = 20;
|
|
|
|
for (let i = 0; i < particleCount; i++) {
|
|
const particle = document.createElement('div');
|
|
particle.className = 'website-particle';
|
|
|
|
// Random size between 5px and 15px
|
|
const size = Math.random() * 10 + 5;
|
|
particle.style.width = `${size}px`;
|
|
particle.style.height = `${size}px`;
|
|
|
|
// Random position
|
|
const posX = Math.random() * 100;
|
|
const posY = Math.random() * 100;
|
|
particle.style.left = `${posX}%`;
|
|
particle.style.top = `${posY}%`;
|
|
particle.style.opacity = Math.random() * 0.5;
|
|
|
|
particleContainer.appendChild(particle);
|
|
|
|
// Animate particles with GSAP
|
|
gsap.to(particle, {
|
|
x: "random(-100, 100)",
|
|
y: "random(-100, 100)",
|
|
opacity: "random(0.1, 0.5)",
|
|
duration: "random(10, 20)",
|
|
repeat: -1,
|
|
repeatRefresh: true,
|
|
ease: "sine.inOut"
|
|
});
|
|
}
|
|
}
|
|
|
|
// Keyboard navigation
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.key === 'ArrowLeft') {
|
|
prevBtn.click();
|
|
} else if (e.key === 'ArrowRight') {
|
|
nextBtn.click();
|
|
}
|
|
});
|
|
|
|
// Touch support for mobile
|
|
let touchStartX = 0;
|
|
let touchEndX = 0;
|
|
|
|
websitesShowcase.addEventListener('touchstart', (e) => {
|
|
touchStartX = e.changedTouches[0].screenX;
|
|
});
|
|
|
|
websitesShowcase.addEventListener('touchend', (e) => {
|
|
touchEndX = e.changedTouches[0].screenX;
|
|
handleSwipe();
|
|
});
|
|
|
|
function handleSwipe() {
|
|
if (touchEndX < touchStartX - 50) {
|
|
// Swipe left
|
|
nextBtn.click();
|
|
} else if (touchEndX > touchStartX + 50) {
|
|
// Swipe right
|
|
prevBtn.click();
|
|
}
|
|
}
|
|
|
|
// Auto-rotate setup
|
|
let autoRotateInterval;
|
|
|
|
function startAutoRotate() {
|
|
autoRotateInterval = setInterval(() => {
|
|
if (!isAnimating) {
|
|
const nextIndex = (currentIndex + 1) % websites.length;
|
|
goToSlide(nextIndex);
|
|
}
|
|
}, 6000);
|
|
}
|
|
|
|
function stopAutoRotate() {
|
|
clearInterval(autoRotateInterval);
|
|
}
|
|
|
|
// Pause on hover
|
|
websitesShowcase.addEventListener('mouseenter', stopAutoRotate);
|
|
websitesShowcase.addEventListener('mouseleave', startAutoRotate);
|
|
|
|
// Start auto rotation
|
|
startAutoRotate();
|
|
|
|
// Add entrance animation for tech features
|
|
const techFeatures = document.querySelectorAll('.tech-feature');
|
|
|
|
gsap.from(techFeatures, {
|
|
y: 50,
|
|
opacity: 0,
|
|
stagger: 0.1,
|
|
duration: 0.8,
|
|
ease: "power2.out",
|
|
scrollTrigger: {
|
|
trigger: techFeatures[0],
|
|
start: "top bottom-=100px",
|
|
toggleActions: "play none none none"
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</register-block>
|