如何在Angular中实现类似Uber Eats的滚动分类栏及动态定位
实现Angular滚动分类栏动态高亮当前视图分类
要实现滚动时自动高亮当前视图对应的分类,你需要添加滚动监听逻辑,结合元素位置判断来更新激活状态,以下是具体修改方案:
1. 更新组件TypeScript代码
添加激活分类变量、滚动监听及位置判断逻辑,同时处理跳转时的激活状态同步:
import { Component, ElementRef, ViewChild, OnInit, OnDestroy } from '@angular/core'; @Component({ selector: 'app-content', templateUrl: './content.component.html', styleUrls: ['./content.component.css'] }) export class ContentComponent implements OnInit, OnDestroy { @ViewChild('pageContent') pageContent!: ElementRef; currentActiveCategory: string = ''; scrollListener?: () => void; scrollToCategory(category: string) { const element = document.getElementById(category); if (element) { element.scrollIntoView({ behavior: 'smooth', block: 'start' }); this.currentActiveCategory = category; // 跳转时直接同步激活状态 } } categories = ['Category 1', 'Category 2', 'Category 3','Category 4', 'Category 5', 'Category 6', 'Category 7','Category 8']; items : any = { 'Category 1': ['Item 1', 'Item 2', 'Item 3'], 'Category 2': ['Item 4', 'Item 5', 'Item 6'], 'Category 3': ['Item 7', 'Item 8', 'Item 9'], 'Category 4': ['Item 7', 'Item 8', 'Item 9'], 'Category 5': ['Item 1', 'Item 2', 'Item 3'], 'Category 6': ['Item 4', 'Item 5', 'Item 6'], 'Category 7': ['Item 7', 'Item 8', 'Item 9'], 'Category 8': ['Item 7', 'Item 8', 'Item 9'], 'Category 9': ['Item 1', 'Item 2', 'Item 3'], 'Category 10': ['Item 4', 'Item 5', 'Item 6'], 'Category 11': ['Item 7', 'Item 8', 'Item 9'], 'Category 12': ['Item 7', 'Item 8', 'Item 9'], 'Category 13': ['Item 1', 'Item 2', 'Item 3'], 'Category 14': ['Item 4', 'Item 5', 'Item 6'], 'Category 15': ['Item 7', 'Item 8', 'Item 9'], 'Category 16': ['Item 7', 'Item 8', 'Item 9'], 'Category 17': ['Item 1', 'Item 2', 'Item 3'], 'Category 18': ['Item 4', 'Item 5', 'Item 6'], 'Category 19': ['Item 7', 'Item 8', 'Item 9'], 'Category 20': ['Item 7', 'Item 8', 'Item 9'], }; ngOnInit() { // 绑定滚动监听事件 this.scrollListener = () => this.checkActiveCategory(); window.addEventListener('scroll', this.scrollListener); // 初始化时检查一次激活状态 this.checkActiveCategory(); } ngOnDestroy() { // 移除监听防止内存泄漏 if (this.scrollListener) { window.removeEventListener('scroll', this.scrollListener); } } private checkActiveCategory() { const scrollTop = window.scrollY + 80; // 80为分类栏高度,需根据实际样式调整 let activeCat = ''; this.categories.forEach(category => { const element = document.getElementById(category); if (element) { const rect = element.getBoundingClientRect(); // 判断元素是否进入当前视图区域 if (rect.top <= scrollTop && rect.bottom > scrollTop) { activeCat = category; } } }); if (activeCat !== this.currentActiveCategory) { this.currentActiveCategory = activeCat; } } }
2. 修改HTML模板
给分类按钮绑定激活样式,同时给页面内容容器添加视图引用:
<div class="category-bar"> <button *ngFor="let category of categories" (click)="scrollToCategory(category)" [class.active]="category === currentActiveCategory" > {{ category }} </button> </div> <div class="page-content" #pageContent> <div *ngFor="let category of categories" id="{{ category }}"> <h2>{{ category }}</h2> <div *ngFor="let item of items[category]">{{ item }}</div> </div> </div>
3. 添加CSS样式
实现分类栏固定顶部、横向滚动及激活按钮高亮效果:
.category-bar { position: fixed; top: 0; left: 0; right: 0; background: white; padding: 1rem; border-bottom: 1px solid #eee; overflow-x: auto; white-space: nowrap; z-index: 100; } .category-bar button { margin: 0 0.5rem; padding: 0.5rem 1rem; border: none; background: transparent; cursor: pointer; transition: color 0.2s; } .category-bar button.active { color: #165DFF; font-weight: bold; border-bottom: 2px solid #165DFF; } .page-content { margin-top: 80px; /* 与分类栏高度一致,避免内容被遮挡 */ padding: 1rem; } /* 给分类区块增加间距,优化滚动体验 */ .page-content > div { margin-bottom: 4rem; padding: 1rem; border: 1px solid #f0f0f0; }
核心逻辑说明
- 滚动监听:组件初始化时绑定窗口滚动事件,每次滚动触发激活状态检查
- 位置判断:通过
getBoundingClientRect()获取元素视口位置,结合滚动距离判断当前视图对应的分类 - 状态同步:点击跳转时直接更新激活状态,滚动时动态计算更新
- 内存防护:组件销毁时移除滚动监听,避免内存泄漏
内容的提问来源于stack exchange,提问作者Akitha Fonseka
相关产品推荐
相关产品推荐

