Angular5动画进度条实现求助:滚动触发+0到目标值动画
解决Angular 5进度条滚动触发动画问题
Hey there! Since you're new to Angular 5 after using jQuery for a while, let's break this down step by step—no jQuery-style DOM hacking needed, we'll do this the Angular way.
第一步:实现进度条从0到指定值的动画
首先,我们先搞定进度条的动画逻辑。我们会用Angular的视图引用(@ViewChild)获取DOM元素,通过逐步递增数值的方式实现平滑动画,比直接修改样式更可控。
组件模板(HTML)
<!-- 进度条容器 --> <div class="progress-container" #progressContainer> <div class="progress-bar" [style.width.%]="progressValue"></div> </div>
组件样式(CSS)
.progress-container { width: 100%; height: 20px; background-color: #eee; border-radius: 10px; overflow: hidden; } .progress-bar { height: 100%; background-color: #4CAF50; transition: none; /* 用JS控制动画,关掉CSS过渡避免冲突 */ }
组件类(TypeScript)
先导入必要的Angular装饰器:
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
然后编写核心逻辑:
@Component({ selector: 'app-progress-bar', templateUrl: './progress-bar.component.html', styleUrls: ['./progress-bar.component.css'] }) export class ProgressBarComponent implements OnInit { progressValue = 0; // 当前进度值 targetValue = 75; // 可替换为任意0-100的数值 animationTriggered = false; // 标记动画是否已触发,避免重复执行 @ViewChild('progressContainer') progressContainer!: ElementRef; ngOnInit() { // 监听window滚动事件 window.addEventListener('scroll', this.checkViewport.bind(this)); } // 检查元素是否进入视口 checkViewport() { if (this.animationTriggered) return; // 已触发则直接返回 const element = this.progressContainer.nativeElement; const rect = element.getBoundingClientRect(); // 判断元素是否进入视口:顶部小于窗口高度,底部大于0 const isInViewport = rect.top < window.innerHeight && rect.bottom > 0; if (isInViewport) { this.animateProgress(); this.animationTriggered = true; // 动画触发后移除滚动监听,优化性能 window.removeEventListener('scroll', this.checkViewport.bind(this)); } } // 基础版进度条动画 animateProgress() { const increment = 1; // 每次递增步长,越小动画越平滑 const duration = 16; // 每步间隔时间(约60fps) const timer = setInterval(() => { if (this.progressValue >= this.targetValue) { clearInterval(timer); this.progressValue = this.targetValue; // 确保最终值准确 return; } this.progressValue += increment; }, duration); } }
进阶:更平滑的时间驱动动画
如果想要更均匀流畅的动画效果,可以把animateProgress替换为基于requestAnimationFrame的版本:
animateProgress() { const startTime = performance.now(); const totalDuration = 1500; // 动画总时长(毫秒) const animateFrame = (currentTime: number) => { const elapsedTime = currentTime - startTime; const progressRatio = Math.min(elapsedTime / totalDuration, 1); this.progressValue = progressRatio * this.targetValue; if (progressRatio < 1) { requestAnimationFrame(animateFrame); } else { this.progressValue = this.targetValue; } }; requestAnimationFrame(animateFrame); }
关键知识点说明
@ViewChild:Angular中获取DOM元素的标准方式,替代jQuery的选择器,更符合组件化思想。- 视口检测:用
getBoundingClientRect()获取元素位置,判断是否进入视口,避免了jQuery式的DOM操作逻辑。 - 数据绑定:通过Angular的双向数据绑定自动更新DOM,比直接操作DOM更安全、更符合框架规范。
内容的提问来源于stack exchange,提问作者Giamma
相关产品推荐
相关产品推荐

