Angular 4 : 封装拖动指令(模态框拖动)

一. 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;
    }
  }
}

 

转载于:https://www.cnblogs.com/xiaojing140421/p/9389259.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值