如何在Angular 5中实现无jQuery的平滑滚动效果
替代jQuery平滑滚动的原生JS与Angular 5实现方案
我来帮你搞定这个问题!你现在需要把依赖jQuery的平滑滚动逻辑改成无依赖的实现,不管是原生JS还是符合Angular 5风格的写法都可以,下面给你两种实用方案:
方案一:原生JavaScript实现(无任何依赖)
这个方案完全脱离jQuery,用requestAnimationFrame实现流畅的动画,还能模拟jQuery默认的缓动效果,精确控制800ms的滚动时长:
function smoothScroll() { // 获取父容器和目标元素 const parentElement = document.querySelector('.parent-class'); const targetElement = document.getElementById('scrllhere'); // 避免元素不存在导致报错 if (!parentElement || !targetElement) return; // 计算目标滚动位置(和你的jQuery逻辑一致:目标元素顶部+10) const targetPosition = targetElement.offsetTop + 10; const startPosition = parentElement.scrollTop; const scrollDistance = targetPosition - startPosition; const duration = 800; // 滚动时长,和原代码一致 let animationStart = null; // 动画帧函数 function animateScroll(currentTime) { if (animationStart === null) animationStart = currentTime; const timeElapsed = currentTime - animationStart; // 计算进度,确保不超过100% const progress = Math.min(timeElapsed / duration, 1); // 加入缓动函数,模拟jQuery animate的默认ease-in-out效果 const easeProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2; // 更新滚动位置 parentElement.scrollTop = startPosition + (scrollDistance * easeProgress); // 未完成则继续调用下一帧 if (timeElapsed < duration) { requestAnimationFrame(animateScroll); } } // 启动动画 requestAnimationFrame(animateScroll); }
如果不需要自定义缓动,现代浏览器还支持更简洁的原生scrollTo方法(注意:部分浏览器不支持自定义时长,behavior: 'smooth'会使用浏览器默认时长):
function smoothScroll() { const parentElement = document.querySelector('.parent-class'); const targetElement = document.getElementById('scrllhere'); if (!parentElement || !targetElement) return; const targetPosition = targetElement.offsetTop + 10; parentElement.scrollTo({ top: targetPosition, behavior: 'smooth' }); }
方案二:Angular 5风格实现
Angular的动画模块主要针对组件状态变化,但我们可以结合ViewChild获取DOM元素引用,保持Angular的组件化规范,同时用原生动画逻辑实现:
第一步:模板中添加引用变量
<!-- 给父容器和目标元素添加模板引用 --> <div #parentContainer class="parent-class"> <!-- 页面内容 --> <div #scrollTarget id="scrllhere">滚动目标位置</div> </div>
第二步:组件类中实现滚动逻辑
import { Component, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html', styleUrls: ['./your-component.component.css'] }) export class YourComponent { // 通过ViewChild获取DOM元素引用 @ViewChild('parentContainer') parentContainer: ElementRef; @ViewChild('scrollTarget') scrollTarget: ElementRef; smoothScroll() { const parentEl = this.parentContainer.nativeElement; const targetEl = this.scrollTarget.nativeElement; if (!parentEl || !targetEl) return; const targetPosition = targetEl.offsetTop + 10; const startPosition = parentEl.scrollTop; const scrollDistance = targetPosition - startPosition; const duration = 800; let animationStart = null; const animateScroll = (currentTime: number) => { if (animationStart === null) animationStart = currentTime; const timeElapsed = currentTime - animationStart; const progress = Math.min(timeElapsed / duration, 1); // 缓动函数 const easeProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2; parentEl.scrollTop = startPosition + (scrollDistance * easeProgress); if (timeElapsed < duration) { requestAnimationFrame(animateScroll); } }; requestAnimationFrame(animateScroll); } }
这个方案避免了直接操作DOM,符合Angular的最佳实践,同时实现了和原jQuery代码完全一致的滚动效果。
内容的提问来源于stack exchange,提问作者Vicky Kumar
相关产品推荐
相关产品推荐

