likes
comments
collection
share

ng-zorro11的modal组件可拖拽(模板创建的弹窗)

作者站长头像
站长
· 阅读数 11

最近在项目中有需求可以拖拽的弹窗,网上搜索了一遍都是服务端创建的弹窗可拖拽,而通过template创建的弹窗确比较难实现,我参考了别人的实现,改造了一下,就可以实现template的拖拽。

1. 创建指令 drag-modal.directive.ts

import { Directive, ElementRef, Input } from '@angular/core';
import { ModalDragService } from "./drag-modal.service";
import { NzModalRef } from 'ng-zorro-antd/modal';
@Directive({
  selector: '[dragModal]'
})
export class DragModalDirective {
  @Input() dragModal: NzModalRef;

  constructor(private ModalDragService: ModalDragService) { 
    setTimeout(() => {
      this.ModalDragService.dragServiceModal(this.dragModal);
    }, 16);
  }
}

2.创建指令服务drag-modal.service.ts

import { Injectable, RendererFactory2 } from '@angular/core';
@Injectable({
  providedIn: 'root'
})
export class ModalDragService {
  constructor(
    private rendererFactory2: RendererFactory2,
  ) { }

  dragTemplateModal(refModal) {
    const render = this.rendererFactory2.createRenderer(null, null);
    const modalBackground = refModal.getElement();
    const modalElement = refModal.getElement().querySelector('.ant-modal-content');
    const modalTitleElement = this.createModalTitleElement(render, modalElement);
    this.dragListen(render, modalTitleElement, modalElement, modalBackground);
  }

  dragServiceModal(refModal) {
    refModal.afterOpen.subscribe(() => {
      const render = this.rendererFactory2.createRenderer(null, null);
      const modalBackground = refModal.getElement();
      const modalElement = refModal.getElement().querySelector('.ant-modal-content');
      const modalTitleElement = this.createModalTitleElement(render, modalElement);
      this.dragListen(render, modalTitleElement, modalElement, modalBackground);
    })
  }

  createModalTitleElement(render, modalElement) {
    let element = document.createElement('div') as any;
    render.setStyle(element, 'width', '100%');
    render.setStyle(element, 'height', '54px');
    render.setStyle(element, 'position', 'absolute');
    render.setStyle(element, 'top', '0');
    render.setStyle(element, 'left', '0');
    render.setStyle(element, 'cursor', 'move');
    render.setStyle(element, '-moz-user-select', 'none');
    render.setStyle(element, '-webkit-user-select', 'none');
    render.setStyle(element, '-ms-user-select', 'none');
    render.setStyle(element, '-khtml-user-select', 'none');
    render.setStyle(element, 'user-select', 'none');
    render.appendChild(modalElement, element);
    return element;
  }
  dragListen(render, modalTitleElement, modalElement, modalBackground) {
    render.listen(modalTitleElement, 'mousedown', function (event) {
      this.mouseDownX = event.clientX;
      this.mouseDownY = event.clientY;
      this.modalX = modalElement.offsetLeft;
      this.modalY = modalElement.offsetTop;
      render.setStyle(modalElement, 'left', `${this.modalX}px`);
      render.setStyle(modalElement, 'top', `${this.modalY}px`);
      this.canMove = true;
    }.bind(this));
    render.listen(modalTitleElement, 'mouseup', function (event) {
      this.canMove = false;
    }.bind(this));
    render.listen(modalBackground, 'mousemove', function (event) {
      if (this.canMove) {
        let moveX = event.clientX - this.mouseDownX;
        let moveY = event.clientY - this.mouseDownY;
        let newModalX = this.modalX + moveX;
        let newModalY = this.modalY + moveY;
        render.setStyle(modalElement, 'left', `${newModalX}px`);
        render.setStyle(modalElement, 'top', `${newModalY}px`);
      }
    }.bind(this));
  }
}

3. 封装为一个moduledrag-modal.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DragModalDirective } from "./drag-modal.directive";
import { ModalDragService } from "./drag-modal.service";

@NgModule({
  providers: [ModalDragService],
  declarations: [DragModalDirective],
  imports: [
    CommonModule,
  ],
  exports: [DragModalDirective]
})
export class ModalDragModule { }

然后把这个模块注入到根模块中,就可以愉快地拖拽了^_^

4.使用#dragModal [dragModal]="dragModal"

<nz-modal 
  #dragModal
  [dragModal]="dragModal">
 </nz-modal>