一. HTML和 CSS
html结构大概如下:
<div class="background"> <div appDrag class="modal"> // 在模态框所在的 div 添加属性 [appDrag] <div class="header drag-title"> <div class="icon-close"></div> </div> <div class="dialog-center"> </div> </div> </div>
.background { // background为模态框后面的覆盖层,大小均设置为100%; position: fixed; width: 100%; height: 100%; top: 0; left: 0; z-index: 3000; background: transparent; -webkit-transition: all 0.3s; transition: all 0.3s; } .modal { // 相对于 background 定位, 位置暂时设置为 0,0,0,0 在指令中将其位置水平垂直居中在页面中间 position: absolute; top: 0; left: 0; bottom: 0; right: 0; width: 514px; height: 290px; z-index: 3100; background: #ffffff; box-shadow: 1px 1px 20px rgba(0,0,0,.3); border-radius: 3px; }
二:创建drag.directive.ts
使用 angular cli 命令自动生成指令drag,该命令会自动在app.module.ts中导入drag指令。
ng g directive directives/drag
或者手动在根模块引入指令:
// 导入指令--->用法类似于组件 import { DragDirective } from './directives/drag.directive'; // 列出程序中的组件 declarations: [ · · · DragDirective ],
三:下面是拖拽指令主要逻辑;
import { Directive, ElementRef, HostListener, OnInit } from '@angular/core'; import { fromEvent } from 'rxjs'; @Directive({ selector: '[appDrag]' }) export class DragDirective implements OnInit { private isDown = false; private disX = 0; private disY = 0; constructor(private el: ElementRef) { } /* ElementRef是一个服务,它赋予我们通过它的nativeElement属性直接访问 "DOM 元素"的能力 */ ngOnInit() { this.el.nativeElement.style.left = (document.documentElement.clientWidth - this.el.nativeElement.offsetWidth) / 2 + 'px'; this.el.nativeElement.style.top = (document.documentElement.clientHeight - this.el.nativeElement.offsetHeight) / 2 + 'px'; /* 模态框距左边的距离是document的宽度减去模态框的宽度除以二,同理得出距上面的距离 */ fromEvent(window, 'resize').subscribe(() => { this.el.nativeElement.style.left = (document.documentElement.clientWidth - this.el.nativeElement.offsetWidth) / 2 + 'px'; this.el.nativeElement.style.top = (document.documentElement.clientHeight - this.el.nativeElement.offsetHeight) / 2 + 'px'; }); /* 监控浏览区大小变化,将其设置在浏览器中间位置 */ } // 点击事件 @HostListener('mousedown', ['$event']) onMousedown(event) { // 禁止选中close if (event.target.className.indexOf('icon-close') !== -1) { return; } console.log(event); if (event.target.className.indexOf('drag-title') !== -1) { // 移动区域 this.isDown = true; this.disX = event.clientX - this.el.nativeElement.offsetLeft; this.disY = event.clientY - this.el.nativeElement.offsetTop; } } // 监听document移动事件事件 @HostListener('document:mousemove', ['$event']) onMousemove(event) { // 判断该元素是否被点击了。 if (this.isDown) { // 移动中; const newdisX = event.clientX; const newdisY = event.clientY; let oLeft = newdisX - this.disX; let oTop = newdisY - this.disY; if (oLeft < 0) { oLeft = 0; } else if (oLeft > document.documentElement.clientWidth - this.el.nativeElement.offsetWidth) { oLeft = document.documentElement.clientWidth - this.el.nativeElement.offsetWidth; } if (oTop < 0) { oTop = 0; } else if (oTop > document.documentElement.clientHeight - this.el.nativeElement.offsetHeight) { oTop = document.documentElement.clientHeight - this.el.nativeElement.offsetHeight; } this.el.nativeElement.style.left = oLeft + 'px'; this.el.nativeElement.style.top = oTop + 'px'; } } // 监听document离开事件 @HostListener('document:mouseup', ['$event']) onMouseup() { // 只用当元素移动过了,离开函数体才会触发。 if (this.isDown) { document.onmousemove = null; document.onmouseup = null; this.isDown = false; } } }