如何在拖拽mat tabs时结合cdk drag drop实现自动滚动?
解决Mat Tab与CDK Drag Drop结合时自动滚动失效问题
问题分析
默认CDK拖拽自动滚动失效,通常是因为mat-tab-nav-bar的样式结构干扰了CDK对滚动容器的识别,或者未正确关联拖拽事件与滚动逻辑。以下是具体解决方案:
步骤1:调整模板结构与事件绑定
修改模板,移除自定义wheel事件,添加CDK拖拽的开始、移动事件绑定,确保滚动容器的样式正确:
<div #docTabGroup mat-tab-nav-bar cdkDropList cdkScrollable cdkDropListOrientation="horizontal" class="example-list" (cdkDropListDropped)="drop($event)" > <div mat-tab-link class="example-box" *ngFor="let timePeriod of timePeriods" cdkDrag (cdkDragStarted)="onDragStarted()" (cdkDragMoved)="onDragMoved($event)" > {{timePeriod}} </div> </div>
步骤2:实现拖拽时的自动滚动逻辑
在组件类中注入ScrollDispatcher,通过监听拖拽事件,根据鼠标位置触发容器滚动:
import { Component, ViewChild, ElementRef } from '@angular/core'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; @Component({ selector: 'app-tab-drag-example', templateUrl: './tab-drag-example.html', styleUrls: ['./tab-drag-example.css'] }) export class TabDragExampleComponent { timePeriods = ['Morning', 'Afternoon', 'Evening', 'Night', 'Weekend', 'Holiday', 'Workday', 'Vacation']; @ViewChild('docTabGroup') tabGroup!: ElementRef<HTMLElement>; private scrollInterval: any; onDragStarted() { // 初始化拖拽状态 } onDragMoved(event: any) { const scrollContainer = this.tabGroup.nativeElement; const mouseX = event.pointerPosition.x; const containerRect = scrollContainer.getBoundingClientRect(); const scrollThreshold = 50; // 距离边缘50px触发滚动 let scrollSpeed = 0; // 判断滚动方向 if (mouseX < containerRect.left + scrollThreshold) { scrollSpeed = -5; } else if (mouseX > containerRect.right - scrollThreshold) { scrollSpeed = 5; } // 执行滚动 if (this.scrollInterval) clearInterval(this.scrollInterval); this.scrollInterval = setInterval(() => { scrollContainer.scrollLeft += scrollSpeed; }, 16); } drop(event: CdkDragDrop<string[]>) { // 拖拽排序逻辑 const item = this.timePeriods.splice(event.previousIndex, 1)[0]; this.timePeriods.splice(event.currentIndex, 0, item); // 停止滚动 if (this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; } } }
步骤3:设置容器样式
确保滚动容器具备横向滚动的基础样式:
.example-list { display: flex; gap: 8px; overflow-x: auto; padding: 8px; white-space: nowrap; /* 隐藏滚动条(可选) */ scrollbar-width: none; } .example-list::-webkit-scrollbar { display: none; } .example-box { padding: 12px 24px; background: #fff; border: 1px solid #ccc; cursor: grab; } .example-box.cdk-drag-preview { box-shadow: 0 4px 8px rgba(0,0,0,0.2); }
核心要点
- 通过
cdkDragMoved事件实时获取鼠标位置,判断是否触发滚动 - 使用定时器实现平滑滚动,模拟CDK原生自动滚动效果
- 确保滚动容器的
overflow-x: auto样式正确生效,为滚动提供基础条件
内容的提问来源于stack exchange,提问作者Sa Hagin
相关产品推荐
相关产品推荐

