前言
项目有需要将NG-ZORRO的Modal对话框修改为可拖拽的并且可点击Modal外的元素。Antd(React版)的Modal组件已经支持了拖拽的功能。而NG-ZORRO好像并没有很好的支持。最后终于结合Angular Material提供的cdk-dragdrop实现了该功能。
版本:
Angular:10.2.0与8.2.3均能复现,10.2.0需多设置一个CSS
NG-ZORRO:同Angular版本即可
实现
源码Demo
Html代码:
<nz-modal nzNoAnimation [nzGetContainer]="container" nzMask="false" nzClassName="modal-dragdrop"(nzAfterOpen)="setModelDragDrop('modal-dragdrop')" [(nzVisible)]="isVisibleDragDrop" nzTitle="可拖拽的Modal"[nzZIndex]="1002" (nzOnCancel)="isVisibleDragDrop = false" [nzFooter]="null"><ng-container *nzModalContent><p>正文内容</p><p>正文内容</p><p>正文内容</p></ng-container></nz-modal>
- nzNoAnimation:关闭动画,防止拖拽中抖动
- nzGetContainer:NG-ZORRO会将所有的Modal统一放在body下的一个div里,该属性能将对应Modal挂载到对应的元素下,目的是防止因拖拽需全局定义的部分样式影响到了其他非拖拽的Modal
- nzMask:取消该Modal的遮罩,因需点击遮罩下的元素,所以取消该遮罩
- nzClassName:本处className只为找到该dom元素,需唯一
- setModelDragDrop:具体看下文ts代码
- nzZIndex:NG-ZORRO-10.0.2新属性,10.0.2需配置该属性大于1000才能浮于默认的空遮罩上层
ts代码:主要是setModelDragDrop方法
setModelDragDrop(className: string) {const modal = document.getElementsByClassName(className)[0];const dragVideo = this.dragDrop.createDrag(modal as HTMLElement);const header = modal.querySelector('.ant-modal-header');dragVideo.withHandles([header as HTMLElement]);dragVideo.withBoundaryElement(document.body);}
- 获取到modal的dom
- 通过dragDrop的createDrag方法将元素设置为可拖拽
- 获取Modal头元素
- 将头元素设置为Modal可拖拽的处理句柄
- 设置边界
最后还有部分样式需要在全局定义:
/* 模态框头部可移动样式,默认挂载到了.modal-container下的modal是需移动的modal,才设置头部游标可移动 */.modal-container .ant-modal-header {cursor: move;}/* 默认的modal带有一个24px的padding-bottom,为了避免在固定区域(body)内移动达不到底边的情况,这里设置0 */.modal-container .ant-modal {padding-bottom: 0;}.modal-container .ant-modal-wrap {/* 通过设置该Css与设置对应Modal的[nzGetContainer]="ElementRef(.modal-container)"使modal能点击窗口外,用于可拖拽的modal */pointer-events: none;/*10.0.2新增*/z-index: 1002;}.cdk-overlay-backdrop {/*10.0.2新增*/pointer-events: none;}
