diff --git a/src/assets/css/portfolio-responsive.css b/src/assets/css/portfolio-responsive.css index eaad452..7392080 100644 --- a/src/assets/css/portfolio-responsive.css +++ b/src/assets/css/portfolio-responsive.css @@ -66,10 +66,6 @@ width: 100%; } - .media { - width: auto; - } - .result-section-box[data-card-count='4'] { grid-template-columns: repeat(2, minmax(0, 1fr)); } diff --git a/src/assets/css/portfolio.css b/src/assets/css/portfolio.css index f299630..92bfc06 100644 --- a/src/assets/css/portfolio.css +++ b/src/assets/css/portfolio.css @@ -1791,7 +1791,7 @@ textarea { overflow: hidden; } .media { - height: 100%; + height: 669px; width: 100%; object-fit: cover; object-position: center; diff --git a/src/assets/js/portfolio.js b/src/assets/js/portfolio.js index 935f0e1..3c03f57 100644 --- a/src/assets/js/portfolio.js +++ b/src/assets/js/portfolio.js @@ -669,68 +669,105 @@ function goToSlide(index) { }, 600); } -showcase.addEventListener('wheel', function(e) { - const currentTime = new Date().getTime(); - const isAtEnd = currentSlideIndex === totalSlides - 1; - const isAtStart = currentSlideIndex === 0; +let isSectionPinned = false; - if ((e.deltaY > 0 && !isAtEnd) || (e.deltaY < 0 && !isAtStart)) { - e.preventDefault(); +// استفاده از Intersection Observer برای فهمیدن اینکه چه زمانی سکشن وارد دید کامل می‌شود +const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + // زمانی که سکشن کاملاً یا بخش زیادی از آن در صفحه است + isSectionPinned = entry.isIntersecting; + }); + }, + { + threshold: 0.1, // حساسیت ورود سکشن به صفحه } +); - if (isAnimating || (currentTime - lastScrollTime < scrollCooldown)) { - return; - } +observer.observe(showcase); + +// showcase.addEventListener('wheel', function(e) { +// const currentTime = new Date().getTime(); +// const isAtEnd = currentSlideIndex === totalSlides - 1; +// const isAtStart = currentSlideIndex === 0; + +// const rect = showcase.getBoundingClientRect(); + +// if (rect.top > 5 && e.deltaY > 0) { +// return; // خارج شدن از تابع و اجازه به اسکرول عادی مرورگر برای بالا آوردن عکس +// } +// if (isAtStart && e.deltaY < 0 && rect.top >= 0) { +// return; +// } + +// if ((e.deltaY > 0 && !isAtEnd) || (e.deltaY < 0 && !isAtStart)) { +// e.preventDefault(); +// } + +// if (isAnimating || (currentTime - lastScrollTime < scrollCooldown)) { +// return; +// } - if (Math.abs(e.deltaY) < 10) return; +// if (Math.abs(e.deltaY) < 10) return; - if (e.deltaY > 0) { - if (!isAtEnd) { - lastScrollTime = currentTime; - goToSlide(currentSlideIndex + 1); +// if (e.deltaY > 0) { +// if (!isAtEnd) { +// lastScrollTime = currentTime; +// goToSlide(currentSlideIndex + 1); +// } +// } else { +// if (!isAtStart) { +// lastScrollTime = currentTime; +// goToSlide(currentSlideIndex - 1); +// } +// } +// }, { passive: false }); + +showcase.addEventListener( + 'wheel', + function (e) { + const currentTime = new Date().getTime(); + const isAtEnd = currentSlideIndex === totalSlides - 1; + const isAtStart = currentSlideIndex === 0; + + // گرفتن موقعیت لحظه‌ای سکشن اصلی + const rect = showcase.getBoundingClientRect(); + + // ۱. بررسی حرکت از بالا به پایین: + // اگر کاربر رو به پایین اسکرول می‌کند ولی سرِ سکشن هنوز به بالای صفحه (سقف) نرسیده است + if (e.deltaY > 0 && rect.top > 5) { + return; // اجازه بده صفحه اسکرول طبیعی شود تا سکشن به سقف بچسبد } - } else { - if (!isAtStart) { - lastScrollTime = currentTime; - goToSlide(currentSlideIndex - 1); + + // ۲. بررسی حرکت از پایین به بالا: + // اگر کاربر رو به بالا اسکرول می‌کند ولی انتهای سکشن هنوز کاملاً بالا نیامده تا مماس شود + // فرمول: rect.bottom باید با ارتفاع پنجره (window.innerHeight) یا نقطه پایانی مماس باشد + if (e.deltaY < 0 && rect.bottom < window.innerHeight - 5) { + return; // اجازه بده صفحه طبیعی بالا برود تا سکشن در موقعیت درست قرار بگیرد } - } -}, { passive: false }); -showcase.addEventListener('touchstart', function(e) { - touchStartY = e.touches[0].clientY; - touchStartX = e.touches[0].clientX; -}, { passive: true }); + // ۳. مدیریت خروج از حالت اسلایدر وقتی به ابتدا یا انتها می‌رسیم: + // اگر در اسلاید اول هستیم و رو به بالا اسکرول می‌کنیم، بگذار صفحه بالا برود + if (isAtStart && e.deltaY < 0 && rect.top >= -5) { + return; + } + // اگر در اسلاید آخر هستیم و رو به پایین اسکرول می‌کنیم، بگذار صفحه پایین برود + if (isAtEnd && e.deltaY > 0 && rect.bottom <= window.innerHeight + 5) { + return; + } -showcase.addEventListener('touchmove', function(e) { - if (!touchStartY) return; + // جلوگیری از اسکرول پیش‌فرض بدنه صفحه در طول انیمیشن اسلایدر + if ((e.deltaY > 0 && !isAtEnd) || (e.deltaY < 0 && !isAtStart)) { + e.preventDefault(); + } - const currentTouchY = e.touches[0].clientY; - const currentTouchX = e.touches[0].clientX; - - const diffY = touchStartY - currentTouchY; - const diffX = touchStartX - currentTouchX; + if (isAnimating || currentTime - lastScrollTime < scrollCooldown) { + return; + } - if (Math.abs(diffX) > Math.abs(diffY)) { - return; - } + if (Math.abs(e.deltaY) < 10) return; - const isAtEnd = currentSlideIndex === totalSlides - 1; - const isAtStart = currentSlideIndex === 0; - - if ((diffY > 0 && !isAtEnd) || (diffY < 0 && !isAtStart)) { - if (e.cancelable) e.preventDefault(); - } else { - return; - } - - const currentTime = new Date().getTime(); - if (isAnimating || (currentTime - lastScrollTime < scrollCooldown)) { - return; - } - - if (Math.abs(diffY) > 50) { - if (diffY > 0) { + if (e.deltaY > 0) { if (!isAtEnd) { lastScrollTime = currentTime; goToSlide(currentSlideIndex + 1); @@ -741,9 +778,130 @@ showcase.addEventListener('touchmove', function(e) { goToSlide(currentSlideIndex - 1); } } - touchStartY = currentTouchY; - } -}, { passive: false }); + }, + { passive: false } +); +showcase.addEventListener('touchstart', function(e) { + touchStartY = e.touches[0].clientY; + touchStartX = e.touches[0].clientX; +}, { passive: true }); + +// showcase.addEventListener('touchmove', function(e) { +// if (!touchStartY) return; + +// const currentTouchY = e.touches[0].clientY; +// const currentTouchX = e.touches[0].clientX; + +// const diffY = touchStartY - currentTouchY; +// const diffX = touchStartX - currentTouchX; + +// if (Math.abs(diffX) > Math.abs(diffY)) { +// return; +// } + +// const rect = showcase.getBoundingClientRect(); +// if (rect.top > 5 && diffY > 0) { +// return; +// } +// const isAtEnd = currentSlideIndex === totalSlides - 1; +// const isAtStart = currentSlideIndex === 0; + +// if (isAtStart && diffY < 0 && rect.top >= 0) { +// return; +// } + +// if ((diffY > 0 && !isAtEnd) || (diffY < 0 && !isAtStart)) { +// if (e.cancelable) e.preventDefault(); +// } else { +// return; +// } + +// const currentTime = new Date().getTime(); +// if (isAnimating || (currentTime - lastScrollTime < scrollCooldown)) { +// return; +// } + +// if (Math.abs(diffY) > 50) { +// if (diffY > 0) { +// if (!isAtEnd) { +// lastScrollTime = currentTime; +// goToSlide(currentSlideIndex + 1); +// } +// } else { +// if (!isAtStart) { +// lastScrollTime = currentTime; +// goToSlide(currentSlideIndex - 1); +// } +// } +// touchStartY = currentTouchY; +// } +// }, { passive: false }); + +showcase.addEventListener( + 'touchmove', + function (e) { + if (!touchStartY) return; + + const currentTouchY = e.touches[0].clientY; + const currentTouchX = e.touches[0].clientX; + + const diffY = touchStartY - currentTouchY; + const diffX = touchStartX - currentTouchX; + + if (Math.abs(diffX) > Math.abs(diffY)) { + return; + } + + const rect = showcase.getBoundingClientRect(); + + // حرکت رو به پایین (انگشت به سمت بالا) و سکشن هنوز به سقف نرسیده + if (diffY > 0 && rect.top > 5) { + return; + } + + // حرکت رو به بالا (انگشت به سمت پایین) و تهِ سکشن هنوز وارد کادر نشده + if (diffY < 0 && rect.bottom < window.innerHeight - 5) { + return; + } + + const isAtEnd = currentSlideIndex === totalSlides - 1; + const isAtStart = currentSlideIndex === 0; + + if (isAtStart && diffY < 0 && rect.top >= -5) { + return; + } + if (isAtEnd && diffY > 0 && rect.bottom <= window.innerHeight + 5) { + return; + } + + if ((diffY > 0 && !isAtEnd) || (diffY < 0 && !isAtStart)) { + if (e.cancelable) e.preventDefault(); + } else { + return; + } + + const currentTime = new Date().getTime(); + if (isAnimating || currentTime - lastScrollTime < scrollCooldown) { + return; + } + + if (Math.abs(diffY) > 50) { + if (diffY > 0) { + if (!isAtEnd) { + lastScrollTime = currentTime; + goToSlide(currentSlideIndex + 1); + } + } else { + if (!isAtStart) { + lastScrollTime = currentTime; + goToSlide(currentSlideIndex - 1); + } + } + touchStartY = currentTouchY; + } + }, + { passive: false } +); showcase.addEventListener('touchend', function() { touchStartY = 0;