Path : /home/vishqocm/pcib.in/assets/js/
File Upload :
Current File : //home/vishqocm/pcib.in/assets/js/cursor_and_progress.js

/**
 * Enhanced Cursor Tracker and Scroll Progress Indicator
 * This script adds a custom animated cursor that follows mouse movement
 * and a progress bar at the top of the screen showing the scroll position
 */

document.addEventListener("DOMContentLoaded", function() {
    // Create cursor elements
    createCursorElements();
    
    // Create scroll progress indicator
    createScrollProgressIndicator();
    
    // Initialize both features
    initCursorTracker();
    initScrollProgressIndicator();
});

/**
 * Creates the DOM elements needed for the custom cursor
 */
function createCursorElements() {
    // Create cursor container
    const cursorContainer = document.createElement('div');
    cursorContainer.className = 'cursor-container';
    
    // Create outer cursor (larger circle)
    const cursorOuter = document.createElement('div');
    cursorOuter.className = 'cursor-outer';
    
    // Create inner cursor (smaller dot)
    const cursorInner = document.createElement('div');
    cursorInner.className = 'cursor-inner';
    
    // Create cursor dot (smallest dot)
    const cursorDot = document.createElement('div');
    cursorDot.className = 'cursor-dot';
    
    // Append cursors to container
    cursorContainer.appendChild(cursorOuter);
    cursorContainer.appendChild(cursorInner);
    cursorContainer.appendChild(cursorDot);
    
    // Add cursor container to body
    document.body.appendChild(cursorContainer);
    
    // Add CSS for cursor elements
    const style = document.createElement('style');
    style.textContent = `
        /* Hide default cursor on body and clickable elements */
        body, a, button, input[type="submit"], input[type="button"], .btn, .filter-btn, .slider-dot, 
        .social-icon, .read-more, .btn-view-profile, .nav-link, .dropdown-item {
            cursor: none !important;
        }
        
        /* Cursor Container */
        .cursor-container {
            position: fixed;
            top: 0;
            left: 0;
            z-index: 9999;
            pointer-events: none;
            will-change: transform;
        }
        
        /* Outer cursor (large circle) */
        .cursor-outer {
            position: fixed;
            width: 40px;
            height: 40px;
            border: 2px solid rgba(78, 115, 223, 0.3);
            border-radius: 50%;
            transform: translate(-50%, -50%);
            transition: width 0.3s, height 0.3s, border 0.3s, transform 0.1s;
            pointer-events: none;
        }
        
        /* Inner cursor (medium dot) */
        .cursor-inner {
            position: fixed;
            width: 10px;
            height: 10px;
            background-color: rgba(78, 115, 223, 0.5);
            border-radius: 50%;
            transform: translate(-50%, -50%);
            transition: width 0.3s, height 0.3s, opacity 0.3s, background-color 0.3s;
            pointer-events: none;
        }
        
        /* Cursor dot (smallest dot at center) */
        .cursor-dot {
            position: fixed;
            width: 4px;
            height: 4px;
            background-color: #4e73df;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            pointer-events: none;
        }
        
        /* Hover state for outer cursor */
        .cursor-hover .cursor-outer {
            width: 50px;
            height: 50px;
            border: 2px solid rgba(78, 115, 223, 0.5);
            background-color: rgba(78, 115, 223, 0.03);
        }
        
        /* Hover state for inner cursor */
        .cursor-hover .cursor-inner {
            width: 15px;
            height: 15px;
            background-color: rgba(78, 115, 223, 0.7);
        }
        
        /* Active state (clicking) for cursors */
        .cursor-active .cursor-outer {
            width: 35px;
            height: 35px;
            border: 2px solid rgba(78, 115, 223, 0.7);
        }
        
        .cursor-active .cursor-inner {
            width: 14px;
            height: 14px;
            background-color: rgba(78, 115, 223, 0.9);
        }
        
        /* Hide cursor on mobile devices */
        @media (max-width: 992px) {
            .cursor-container, .cursor-outer, .cursor-inner, .cursor-dot {
                display: none;
            }
            
            body, a, button, input[type="submit"], input[type="button"], .btn {
                cursor: auto !important;
            }
        }
    `;
    document.head.appendChild(style);
}

/**
 * Creates the DOM element for scroll progress indicator
 */
function createScrollProgressIndicator() {
    // Create progress bar container
    const progressContainer = document.createElement('div');
    progressContainer.className = 'scroll-progress-container';
    
    // Create progress bar
    const progressBar = document.createElement('div');
    progressBar.className = 'scroll-progress-bar';
    
    // Append progress bar to container
    progressContainer.appendChild(progressBar);
    
    // Add progress container to body
    document.body.appendChild(progressContainer);
    
    // Add CSS for progress bar
    const style = document.createElement('style');
    style.textContent = `
        /* Progress bar container */
        .scroll-progress-container {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 4px;
            background-color: rgba(0, 0, 0, 0.05);
            z-index: 9998;
        }
        
        /* Progress bar */
        .scroll-progress-bar {
            height: 100%;
            width: 0;
            background: linear-gradient(to right, #4e73df, #36b9cc);
            transition: width 0.1s ease;
            position: relative;
        }
        
        .scroll-progress-bar::after {
            content: '';
            position: absolute;
            top: 0;
            right: 0;
            width: 100%;
            height: 100%;
            background: linear-gradient(to right, 
                rgba(255, 255, 255, 0) 0%, 
                rgba(255, 255, 255, 0.4) 50%, 
                rgba(255, 255, 255, 0) 100%);
            animation: shimmer 1.5s infinite;
            transform: translateX(-100%);
        }
        
        @keyframes shimmer {
            100% {
                transform: translateX(100%);
            }
        }
    `;
    document.head.appendChild(style);
}

/**
 * Initializes the custom cursor tracker
 */
function initCursorTracker() {
    const cursorOuter = document.querySelector('.cursor-outer');
    const cursorInner = document.querySelector('.cursor-inner');
    const cursorDot = document.querySelector('.cursor-dot');
    const cursorContainer = document.querySelector('.cursor-container');
    
    // Cursor positions with damping effect
    let outerX = 0, outerY = 0;
    let innerX = 0, innerY = 0;
    let dotX = 0, dotY = 0;
    
    // Target positions (mouse position)
    let mouseX = 0, mouseY = 0;
    
    // Track mouse movement
    document.addEventListener('mousemove', function(e) {
        mouseX = e.clientX;
        mouseY = e.clientY;
    });
    
    // Detect hover on clickable elements
    const clickableElements = document.querySelectorAll('a, button, input[type="submit"], input[type="button"], .btn, .filter-btn, .slider-dot, .social-icon, .read-more, .btn-view-profile, .nav-link, .dropdown-item');
    
    clickableElements.forEach(el => {
        el.addEventListener('mouseenter', () => {
            cursorContainer.classList.add('cursor-hover');
        });
        
        el.addEventListener('mouseleave', () => {
            cursorContainer.classList.remove('cursor-hover');
        });
    });
    
    // Detect mouse down/up events for click animation
    document.addEventListener('mousedown', () => {
        cursorContainer.classList.add('cursor-active');
    });
    
    document.addEventListener('mouseup', () => {
        cursorContainer.classList.remove('cursor-active');
    });
    
    // Update cursor position with damping effect (smooth following)
    function updateCursorPosition() {
        // Damping factors (smaller = smoother but slower)
        const outerDampingFactor = 0.15;
        const innerDampingFactor = 0.22;
        const dotDampingFactor = 0.3;
        
        // Update outer cursor position with damping
        outerX += (mouseX - outerX) * outerDampingFactor;
        outerY += (mouseY - outerY) * outerDampingFactor;
        
        // Update inner cursor position with damping
        innerX += (mouseX - innerX) * innerDampingFactor;
        innerY += (mouseY - innerY) * innerDampingFactor;
        
        // Update dot cursor position with damping
        dotX += (mouseX - dotX) * dotDampingFactor;
        dotY += (mouseY - dotY) * dotDampingFactor;
        
        // Apply positions to cursor elements
        cursorOuter.style.transform = `translate(${outerX}px, ${outerY}px) translate(-50%, -50%)`;
        cursorInner.style.transform = `translate(${innerX}px, ${innerY}px) translate(-50%, -50%)`;
        cursorDot.style.transform = `translate(${dotX}px, ${dotY}px) translate(-50%, -50%)`;
        
        // Continue animation
        requestAnimationFrame(updateCursorPosition);
    }
    
    // Start animation
    updateCursorPosition();
}

/**
 * Initializes the scroll progress indicator
 */
function initScrollProgressIndicator() {
    const progressBar = document.querySelector('.scroll-progress-bar');
    
    // Update progress bar width on scroll
    window.addEventListener('scroll', function() {
        const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
        const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
        const scrolled = (winScroll / height) * 100;
        progressBar.style.width = scrolled + "%";
    });
}

/**
 * Add these scripts to the main page by calling:
 * <script src="assets/js/cursor_and_progress.js"></script>
 * 
 * Or by inline including this entire JavaScript file
 */