File manager - Edit - /home/webapp69.cm.in.th/u69319090027/01_portfolio/script.js
Back
/* ------------------------------------------------------------- * Custom Cyberpunk / Tech-Futuristic Script (script.js) * Designed for: Suraphot Yakanmoon (Computer Technology Portfolio) * ------------------------------------------------------------- */ document.addEventListener('DOMContentLoaded', () => { // --------------------------------------------------------- // 1. MOBILE DRAWER NAVIGATION // --------------------------------------------------------- const mobileMenuBtn = document.getElementById('mobile-menu-btn'); const mobileMenu = document.getElementById('mobile-menu'); const mobileLinks = document.querySelectorAll('.mobile-nav-link'); if (mobileMenuBtn && mobileMenu) { mobileMenuBtn.addEventListener('click', () => { mobileMenuBtn.classList.toggle('open'); mobileMenu.classList.toggle('hidden'); }); // Close drawer when link is clicked mobileLinks.forEach(link => { link.addEventListener('click', () => { mobileMenuBtn.classList.remove('open'); mobileMenu.classList.add('hidden'); }); }); } // --------------------------------------------------------- // 2. DYNAMIC TYPING ANIMATION (Hero Section) // --------------------------------------------------------- const typingText = document.getElementById('typing-text'); const professions = [ 'COMPUTER TECHNOLOGY STUDENT', 'HARDWARE & CIRCUIT ENGINEER', 'IOT SYSTEM DEVELOPER', 'NETWORKING & SERVER LABS', 'WEB SYSTEM PROGRAMMER' ]; let professionIndex = 0; let charIndex = 0; let isDeleting = false; let typeSpeed = 100; function typeEffect() { if (!typingText) return; const currentText = professions[professionIndex]; if (isDeleting) { typingText.textContent = currentText.substring(0, charIndex - 1); charIndex--; typeSpeed = 50; // Deleting is faster } else { typingText.textContent = currentText.substring(0, charIndex + 1); charIndex++; typeSpeed = 120; // Normal typing speed } // Handle states if (!isDeleting && charIndex === currentText.length) { isDeleting = true; typeSpeed = 1500; // Pause at full text } else if (isDeleting && charIndex === 0) { isDeleting = false; professionIndex = (professionIndex + 1) % professions.length; typeSpeed = 500; // Pause before typing next word } setTimeout(typeEffect, typeSpeed); } // Start typing loop setTimeout(typeEffect, 500); // --------------------------------------------------------- // 3. BACKGROUND CANVAS PARTICLES GRID // --------------------------------------------------------- const canvas = document.getElementById('cyber-bg'); if (canvas) { const ctx = canvas.getContext('2d'); let width = canvas.width = window.innerWidth; let height = canvas.height = window.innerHeight; const particles = []; const maxParticles = 60; // Particle class representing nodes class Particle { constructor() { this.x = Math.random() * width; this.y = Math.random() * height; this.size = Math.random() * 2 + 1; this.speedX = (Math.random() - 0.5) * 0.6; this.speedY = (Math.random() - 0.5) * 0.6; } update() { this.x += this.speedX; this.y += this.speedY; // Bounce boundaries if (this.x < 0 || this.x > width) this.speedX *= -1; if (this.y < 0 || this.y > height) this.speedY *= -1; } draw() { ctx.fillStyle = '#00f0ff'; ctx.shadowBlur = 8; ctx.shadowColor = '#00f0ff'; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); ctx.shadowBlur = 0; // reset } } // Initialize particles for (let i = 0; i < maxParticles; i++) { particles.push(new Particle()); } // Animation loop function animateParticles() { ctx.clearRect(0, 0, width, height); // Connect particles with network lines ctx.strokeStyle = 'rgba(0, 85, 255, 0.08)'; ctx.lineWidth = 1; for (let i = 0; i < particles.length; i++) { for (let j = i + 1; j < particles.length; j++) { const dist = Math.hypot(particles[i].x - particles[j].x, particles[i].y - particles[j].y); if (dist < 150) { ctx.beginPath(); ctx.moveTo(particles[i].x, particles[i].y); ctx.lineTo(particles[j].x, particles[j].y); ctx.stroke(); } } } // Draw and update particles particles.forEach(p => { p.update(); p.draw(); }); requestAnimationFrame(animateParticles); } animateParticles(); // Handle resize events smoothly window.addEventListener('resize', () => { width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; }); } // --------------------------------------------------------- // 4. ACTIVE MENU SCROLL HIGHLIGHTING & SCROLL-TOP BUTTON // --------------------------------------------------------- const sections = document.querySelectorAll('section'); const navLinks = document.querySelectorAll('.nav-link'); const scrollTopBtn = document.getElementById('scroll-top-btn'); window.addEventListener('scroll', () => { let currentSectionId = ''; const scrollPosition = window.scrollY + 100; // offset // Scroll back to top visibility handling if (scrollTopBtn) { if (window.scrollY > 400) { scrollTopBtn.classList.remove('opacity-0', 'pointer-events-none'); scrollTopBtn.classList.add('opacity-100'); } else { scrollTopBtn.classList.add('opacity-0', 'pointer-events-none'); scrollTopBtn.classList.remove('opacity-100'); } } sections.forEach(section => { const sectionTop = section.offsetTop; const sectionHeight = section.clientHeight; if (scrollPosition >= sectionTop && scrollPosition < (sectionTop + sectionHeight)) { currentSectionId = section.getAttribute('id'); } }); navLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('href') === `#${currentSectionId}`) { link.classList.add('active'); } }); }); // --------------------------------------------------------- // 5. PROJECT ARCHIVE TABS FILTER // --------------------------------------------------------- const filterButtons = document.querySelectorAll('.project-filter-btn'); const projectCards = document.querySelectorAll('.project-card'); filterButtons.forEach(btn => { btn.addEventListener('click', () => { // Manage button active class filterButtons.forEach(b => b.classList.remove('active')); btn.classList.add('active'); const filterValue = btn.getAttribute('data-filter'); projectCards.forEach(card => { const category = card.getAttribute('data-category'); if (filterValue === 'all' || category === filterValue) { card.style.display = 'flex'; } else { card.style.display = 'none'; } }); }); }); // --------------------------------------------------------- // 6. CONTACT FORM MESSAGE TRANSMISSION MODAL // --------------------------------------------------------- const contactForm = document.getElementById('cyber-contact-form'); const successModal = document.getElementById('success-modal'); if (contactForm && successModal) { contactForm.addEventListener('submit', (e) => { e.preventDefault(); // Show successful message transaction modal successModal.classList.remove('opacity-0', 'pointer-events-none'); successModal.classList.add('opacity-100'); // Reset fields contactForm.reset(); }); } }); // ------------------------------------------------------------- // 7. EXTERNAL UTILITY TRIGGERS // ------------------------------------------------------------- // Clipboard copying utility function copyToClipboard(text, elementId) { navigator.clipboard.writeText(text).then(() => { const copyStatus = document.getElementById(elementId); if (copyStatus) { copyStatus.classList.remove('opacity-0'); copyStatus.classList.add('opacity-100'); setTimeout(() => { copyStatus.classList.remove('opacity-100'); copyStatus.classList.add('opacity-0'); }, 2000); } }).catch(err => { console.error('Failed to copy matrix credentials: ', err); }); } // Modal dismiss function function closeModal() { const successModal = document.getElementById('success-modal'); if (successModal) { successModal.classList.add('opacity-0', 'pointer-events-none'); successModal.classList.remove('opacity-100'); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.31 |
proxy
|
phpinfo
|
Settings