Digital Consulting | IT Loyihalar 0 ? lineWrapRect.width : 200; canvas.height = (sectionRect.height > 0 ? sectionRect.height : 2000) * 0.75; console.log('✅ Canvas yaratildi:', { width: canvas.width, height: canvas.height, lineWrapHeight: lineWrapRect.height, sectionHeight: sectionRect.height }); const ctx = canvas.getContext('2d'); // ======================================================================== // WAVY LINE PATH - DASHED WHITE LINE (ORIGINAL CHALLENGE STYLE) // ======================================================================== console.log('📐 DASHED WHITE line yaratish...\n'); // Challenge section uchun mayin to'lqin - original style const waveAmplitude = 15; // Juda kichik to'lqin - mayinroq uchun const wavelength = 130; // Uzunroq to'lqin - silliqroq uchun const totalHeight = canvas.height; // ======================================================================== // DRAW FUNCTION - DASHED WHITE STYLE // ======================================================================== function drawLine(progress) { ctx.clearRect(0, 0, canvas.width, canvas.height); // DASHED WHITE STYLE - Original challenge section uchun ctx.strokeStyle = '#c5c5c5ff'; ctx.lineWidth = 1; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; // Dashed line - original style ctx.setLineDash([15, 15]); ctx.beginPath(); const centerX = canvas.width / 2 - 10; // Chaproqqa surish const maxY = totalHeight * progress * 0.9; ctx.moveTo(centerX, 0); // Tekis to'lqinlar let y = 0; let direction = 1; while (y < maxY) { const nextY = Math.min(y + wavelength, maxY); // Oxirgi segmentda egri chizmaslik uchun tekshirish if (nextY >= maxY) { // Oxirgi nuqtaga to'g'ri chiziq ctx.lineTo(centerX, maxY); break; } const controlY = y + (nextY - y) / 2; // Tekis bezier ctx.quadraticCurveTo( centerX + (waveAmplitude * direction), controlY, centerX, nextY ); y = nextY; direction *= -1; } ctx.stroke(); } console.log('✅ DASHED WHITE draw function tayyor\n'); // ======================================================================== // TEST DRAW // ======================================================================== console.log('🧪 Test: To\'liq line chizish...'); drawLine(1); // 100% line setTimeout(() => { console.log('\n' + '='.repeat(70)); console.log('🔍 CHALLENGE LINE KO\'RINISHI KERAK!'); console.log('='.repeat(70)); console.log('Agar ko\'rinsa → ✅ Canvas ishlayapti!'); console.log('Scroll qilsangiz animatsiya boshlanadi'); console.log('='.repeat(70) + '\n'); }, 2000); // ======================================================================== // SCROLL ANIMATION // ======================================================================== console.log('📜 Scroll listener qo\'shish...\n'); let ticking = false; const state = { section, canvas, ctx, pointBlocks, drawLine }; window.addEventListener('scroll', () => { if (!ticking) { requestAnimationFrame(() => { handleScroll(state); ticking = false; }); ticking = true; } }); // Initial draw drawLine(0); console.log('='.repeat(70)); console.log('✅ CHALLENGE ANIMATION TAYYOR!'); console.log('='.repeat(70)); console.log(''); } // ============================================================================ // SCROLL HANDLER // ============================================================================ function handleScroll(state) { const rect = state.section.getBoundingClientRect(); const vh = window.innerHeight; const start = vh * 0.7; const end = vh * 0.2; let progress = 0; if (rect.top < start && rect.bottom > end) { const scrolled = start - rect.top; const total = rect.height - (start - end); progress = Math.max(0, Math.min(1, scrolled / total)); } else if (rect.bottom <= end) { progress = 1; } // Draw line state.drawLine(progress); // Update points state.pointBlocks.forEach((block, i) => { const threshold = (i + 1) / (state.pointBlocks.length + 1); const num = block.querySelector('.point-block__num'); const title = block.querySelector('.point-block_content__title'); const text = block.querySelector('.point-block_content__text'); if (progress >= threshold) { if (num) { num.style.opacity = '1'; num.style.transform = 'scale(1)'; if (!num.classList.contains('active')) { num.classList.add('active'); console.log(`✨ Challenge Point ${i+1} active`); } } if (title) title.style.opacity = '1'; if (text) text.style.opacity = '1'; } else { if (num) { num.style.opacity = '0.4'; num.style.transform = 'scale(0.9)'; num.classList.remove('active'); } if (title) title.style.opacity = '0.7'; if (text) text.style.opacity = '0.7'; } }); } // ============================================================================ // STYLES // ============================================================================ const style = document.createElement('style'); style.textContent = ` .challenge .line-wrap1 { position: absolute !important; margin-left: -17px !important; margin-top: 4px !important; bottom: 0 !important; width: 190px !important; height: 100% !important; opacity: 1 !important; } .challenge .point-block__num { transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55); opacity: 0.4; transform: scale(0.9); } .challenge .point-block__num.active { } .challenge .point-block_content__title, .challenge .point-block_content__text { opacity: 1; transform: translateX(0px); transition: all 0.6s ease-out; } `; document.head.appendChild(style); // ============================================================================ // START // ============================================================================ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { setTimeout(init, 100); } })();