Angular实现div容器左右双向拖拽调整宽度方法
问题结论
HTML 原生div没有内置拖拽调整宽度的能力,但完全可以通过指针事件监听实现左右双向拖拽调整宽度。你现有代码已经实现了基础拖拽框架,只需要补充方向判断逻辑、记录拖拽初始状态即可实现从右向左拖拽调整的效果,不需要重构整体逻辑。
现有代码问题
你当前实现的核心问题有4个:
- 拖拽开始时没有记录鼠标起始位置、容器初始宽度、初始偏移值,宽度计算完全依赖全局视口位置,拖拽容易跳变
- 宽度计算逻辑写死了单方向规则,没有根据
expandDirection区分左右拖拽的计算差异 - 左边缘拖拽时没有同步调整容器的
left偏移,会导致容器宽度变化时右边缘位置错位 - 拖拽手柄定位逻辑写反,且父容器缺少相对定位,手柄位置容易偏移
具体修改步骤
1. 补充拖拽初始状态记录
在组件类中新增私有变量存储拖拽起始值,修改onMouseDown方法在拖拽触发时记录初始状态:
// 类属性区新增 private startX = 0; private startWidth = 0; private startLeft = 0; // 修改onMouseDown onMouseDown(event: MouseEvent) { event.preventDefault(); this.isResizing = true; this.startX = event.clientX; this.startWidth = this.width; this.startLeft = this.left; }
2. 重写拖拽移动时的尺寸计算逻辑
替换原有onMouseMove中写死的宽度计算规则,根据扩展方向分别计算宽度和偏移:
@HostListener('window:mousemove', ['$event']) onMouseMove(event: MouseEvent) { if (!this.isResizing) return; const elem = this.elementRef.nativeElement as HTMLDivElement; const deltaX = event.clientX - this.startX; const minWidth = 80; // 可自定义最小拖拽宽度,避免出现负宽度 let newWidth = this.startWidth; let newLeft = this.startLeft; if (this.expandDirection === 'RIGHT') { // 拖拽右边缘场景:左边缘位置固定,向右拖拽宽度增加 newWidth = Math.max(minWidth, this.startWidth + deltaX); } else { // 拖拽左边缘场景:右边缘位置固定,向左拖拽宽度增加,同步偏移left值 newWidth = Math.max(minWidth, this.startWidth - deltaX); newLeft = this.startLeft + deltaX; } this.left = newLeft; this.updateWidthHeight(elem, newWidth, this.height); }
3. 修正拖拽手柄定位逻辑
修改getGrabberDirection方法,修正手柄位置和扩展方向的对应关系:
getGrabberDirection(){ // 向左扩展时手柄在容器左边缘,向右扩展时手柄在容器右边缘 return this.expandDirection === 'LEFT' ? { left: '0px' } : { right: '0px' }; }
4. 补充样式定位规则
给父容器加相对定位,保证拖拽手柄位置正确:
div#resizer-container { position: relative; // 新增:作为绝对定位手柄的定位父级 display: flex; flex-flow: row nowrap; div#grabber-width { width: 8px; height: 100%; position: absolute; top: 0; // 新增:保证手柄垂直撑满容器 cursor: col-resize; z-index: 10; // 新增:避免手柄被内容遮挡无法拖拽 } }
效果说明
- 传入
expandDirection="RIGHT"时,拖拽手柄显示在容器右边缘,拖拽时容器左边缘位置固定,向右拉宽、向左拉窄 - 传入
expandDirection="LEFT"时,拖拽手柄显示在容器左边缘,拖拽时容器右边缘位置固定,向左拉宽、向右拉窄 - 如果需要同时支持左右双向拖拽,只需要在模板中加第二个拖拽手柄,分别绑定不同的方向标识即可实现两边都能拖的效果
内容的提问来源于stack exchange,提问作者winppw
相关产品推荐
相关产品推荐

