如何优化背景视差效果,提升滚动操作时的流畅度?
背景视差滚动卡顿问题
当前背景视差在触摸板滚动、滚动条拖动时出现卡顿现象,但点击锚点跳转时滚动流畅。具体表现:
- 使用鼠标滚轮滚动、慢速拖动滚动条、点击滚动条上下箭头时,图像滚动均不流畅
- 快速拖动滚动条时则无明显卡顿
相关实现代码
JavaScript 代码
document.addEventListener('DOMContentLoaded', function() { const sections = document.querySelectorAll('#parallax'); const maxOffset = 900; // 最终状态:向下400px。"400px"是调整不同屏幕尺寸代码的参考值,不属于逻辑部分 const maxZoom = 1.4; // 值越小,缩放比例越小 function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function updateParallax() { const windowHeight = window.innerHeight; sections.forEach(section => { const rect = section.getBoundingClientRect(); const sectionHeight = rect.height; /* 总滚动范围: 开始:当区块底部到达视口底部时 结束:当区块顶部到达视口顶部时 */ const totalTravel = windowHeight + sectionHeight; // 已滚动的距离 const traveled = windowHeight - rect.top; let progress = traveled / totalTravel; progress = clamp(progress, 0, 1); // 更平滑的运动曲线 const eased = Math.pow(progress, 1.4); // 0 -> 400px 向下偏移 const y = eased * maxOffset; // 1 -> 1.4 缩放比例 const scale = 1 + eased * maxZoom; section.style.setProperty('--parallax-offset', `${y}px`); section.style.setProperty('--parallax-scale', scale); }); } let ticking = false; function onScroll() { if (!ticking) { requestAnimationFrame(() => { updateParallax(); ticking = false; }); ticking = true; } } window.addEventListener('scroll', onScroll, { passive: true }); window.addEventListener('resize', onScroll); updateParallax(); }); // 平滑滚动逻辑 document.addEventListener('DOMContentLoaded', function() { const header = document.querySelector('header'); function getHeaderHeight() { return header ? header.offsetHeight : 0; } function smoothScrollTo(target, duration) { const start = window.pageYOffset; const headerOffset = getHeaderHeight(); const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - headerOffset; const distance = targetPosition - start; let startTime = null; function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2; } function animation(currentTime) { if (startTime === null) startTime = currentTime; const timeElapsed = currentTime - startTime; const progress = Math.min(timeElapsed / duration, 1); const ease = easeInOutQuad(progress); window.scrollTo(0, start + distance * ease); if (timeElapsed < duration) { requestAnimationFrame(animation); } } requestAnimationFrame(animation); } document.querySelectorAll('a[href*="#"]:not(.popup-open)').forEach(function(anchor) { anchor.addEventListener('click', function(e) { const href = this.getAttribute('href'); const hashIndex = href.indexOf('#'); if (hashIndex === -1) return; const targetId = href.substring(hashIndex); if (!targetId || targetId === '#') return; const target = document.querySelector(targetId); if (target) { e.preventDefault(); smoothScrollTo(target, 2000); } }); }); });
CSS 代码
html { scroll-behavior: auto; /* 禁用默认滚动行为 */ } #parallax { position: relative; overflow: hidden; /* min-height: 100vh; */ --parallax-offset: 0px; --parallax-scale: 1; } #parallax::before { content: ""; position: absolute; top: -60%; left: 0%; width: 80%; height: 76%; background-image: url('https://i.sstatic.net/Cb72ZEgr.jpg'); background-size: cover; background-position: center 45%; background-repeat: no-repeat; transform: translate3d(0, var(--parallax-offset), 0) scale(var(--parallax-scale)); transform-origin: 50% 2%; will-change: transform; z-index: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; contain: paint; } #parallax>.e-con-inner { position: relative; z-index: 2; } @media (min-width: 1530px) { #parallax::before { top: -70%; width: 80%; height: 86%; transform-origin: 50% 2%; } } @media (min-width: 580px) and (max-height: 800px) { #parallax::before { background-image: url('https://i.sstatic.net/EDudN3ZP.jpg'); top: -80%; width: 100%; height: 100%; transform-origin: 50% 10%; background-size: contain; } } @media (min-width: 1900px) { #parallax::before { background-image: url('https://i.sstatic.net/JpACme02.jpg'); background-position: center 0%; top: -136%; width: 100%; height: 112%; transform-origin: 50% 10%; background-size: contain; } } @media (min-width: 1900px) and (max-height: 1000px) { #parallax::before { background-image: url('https://i.sstatic.net/EDudN3ZP.jpg'); background-position: center 0%; top: -100%; width: 100%; height: 102%; transform-origin: 50% 10%; background-size: contain; } } @media (max-width: 1024px) { #parallax::before { top: -80%; } } @media (min-width: 360px) and (max-width: 767px) { #parallax::before { top: -50%; left: 10%; } }
HTML 代码
<a href="#footer">to footer</a> <div class="elementor-element elementor-element-2d33ef6 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-parent e-lazyloaded" data-id="2d33ef6" data-element_type="container" data-e-type="container" id="parallax"> <div class="e-con-inner"> <div class="elementor-element elementor-element-afd013c e-con-full e-flex wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-child" data-id="afd013c" data-element_type="container" data-e-type="container"> <div class="elementor-element elementor-element-de7cf26 e-con-full spacearound e-flex wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-child" data-id="de7cf26" data-element_type="container" data-e-type="container" data-settings="{"background_background":"classic"}"> <div class="elementor-element elementor-element-78b633b elementor-widget elementor-widget-text-editor" data-id="78b633b" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default"> <h1 style="text-align: center; font-size: 60px;">Lorem ipsum</h1> </div> <div> <h2 style="text-align: center; font-weight: 300;"><span style="color: inherit; font-family: inherit; font-size: 2rem;">Lorem ipsum dolor sit </span></h2> </div> <div> <h2 style="text-align: center;"><img src="https://i.sstatic.net/O9FcKWC1.png" style="width: 60px; height: 60px"alt="logo"></h2> </div> <div> <p style="text-align: center; font-size: 26px;"><strong>amet consectetur adipiscing elit</strong></p> </div> <div class="elementor-element elementor-element-f6da976 elementor-align-center elementor-widget elementor-widget-button" data-id="f6da976" data-element_type="widget" data-e-type="widget" data-widget_type="button.default"> </div> </div> </div> </div> </div> <div> <p> Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. </p> <p> Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. </p> <p> Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. </p> <p> Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. </p> <p> Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. </p> <div id="footer"></div> </div>
实际场景中该卡顿表现比代码示例更显著。
内容的提问来源于stack exchange,提问作者iorgu
相关产品推荐
相关产品推荐

