美文网首页
自定义anglular拖拽指令

自定义anglular拖拽指令

作者: 甘道夫老矣 | 来源:发表于2022-11-28 14:46 被阅读0次

    场景:页面一个div框,或者工具框,需要实现拖拽,不用固定

    1.指令文件

    import { Directive, ElementRef, HostListener, Input, Output, EventEmitter, OnInit } from '@angular/core';
    import * as $ from 'jquery';
    
    @Directive({
        selector: '[appDraggable]'
    })
    export class DraggableDirective {
        @Output() mouseEnter = new EventEmitter<boolean>();
        element: any = null;
    
    
        private disX = 0;
        private disY = 0;
        private isDown = false;
        private parentDiv;
    
        constructor(private ref: ElementRef) {
            // console.log(ref);
            this.element = this.ref.nativeElement;
        }
        @HostListener('drag', ['event'])
        dragEvent(): void {
            // console.log('drag');
        }
    
        @HostListener('mouseenter', ['$event'])   // 一个装饰器,用于声明要监听的 DOM 事件,并提供在该事件发生时要运行的处理器方法。
        onMouseEnter(ev: any): void {
            ev.stopPropagation();
            // console.log('拖拽-移入');
            this.mouseEnter.emit(true);
        }
    
        @HostListener('mouseleave', ['$event'])
        onMouseLeave(ev: any): void {
            ev.stopPropagation();
            // console.log('拖拽-移出');
            document.onmousemove = null;
            document.onmouseup = null;
            this.isDown = false;
            this.changeDownStyle();
            this.mouseEnter.emit(false);
        }
    
    
        // 1.是否为顶级
        isParent(obj, parentObj): any {
            // 判断当前存不存在,是不是body,并且是不是点的这个dom
            if (obj !== undefined &&
                obj != null &&
                obj.tagName.toUpperCase() !== 'BODY') {
                if (obj === parentObj) {
                    return { ifContain: true, evDom: parentObj };
                } else {
                    // 判断当前点击的父级是否包含当前有拖拽的元素
                    const parAll = $(obj).parents();
                    let ifContain = false;
                    // tslint:disable-next-line:prefer-for-of
                    for (let i = 0; i < parAll.length; i++) {
                        const element = parAll[i];
                        if (element === parentObj) {
                            ifContain = true;
                            break;
                        }
                    }
                    if (ifContain) {
                        return { ifContain, evDom: parentObj };
                    } else {
                        return { ifContain };
                    }
    
                }
            } else {
                return { ifContain: false };
            }
        }
    
        // 点击事件 按下鼠标时,获取当前的定位
        @HostListener('document:mousedown', ['$event'])
        onMouseDown(ev: any): void {
            ev.stopPropagation();
            // console.log('按下鼠标');
            const isParent = this.isParent(ev.target, this.element);
            if (isParent.ifContain) {
    
                let evParentNode = ev.target.parentNode;
                // 判断当前点击的dom,是否在当前拖拽的dom中,如果是,那么就直接获取当前绑定拖拽的dom元素
                if (isParent.evDom) {
                    evParentNode = isParent.evDom.parentNode;
                }
                // 获取当前点击的div相对的父级div;(注意:这里的父级一定要是最顶级那种,宽100%,长100%,否则无效)
                if (evParentNode && evParentNode.clientHeight > 0 && evParentNode.clientWidth > 0) {
                    this.parentDiv = evParentNode;
                } else {
                    this.parentDiv = document.querySelector('body');
                }
    
                this.disX = ev.clientX - this.element.offsetLeft;
                this.disY = ev.clientY - this.element.offsetTop;
                // 移动区域
                this.isDown = true;
                this.changeDownStyle();
            }
        }
    
    
        /**
         * 监听document移动事件事件    鼠标移动时
         */
        @HostListener('document:mousemove', ['$event'])
        onMouseMove(ev: any): void {
            ev.stopPropagation();
            if (this.isDown) {
                // console.log('开始移动');
                // 获取父元素的宽高
                const cw = this.parentDiv.clientWidth;
                const cy = this.parentDiv.clientHeight;
                // 当前块的宽高
                const dw = this.element.offsetWidth;
                const dh = this.element.offsetHeight;
    
                let oLeft = ev.clientX - this.disX;
                let oTop = ev.clientY - this.disY;
                // top定位位置
                if (oTop < 0) {
                    oTop = 0;
                } else if (oTop >= cy - dh) {
                    oTop = cy - dh;
                }
    
                // left定位位置
                if (oLeft < 0) {
                    oLeft = 0;
                } else if (oLeft >= cw - dw) {
                    oLeft = cw - dw;
                }
    
                this.element.style.left = oLeft + 'px';
                this.element.style.top = oTop + 'px';
            }
    
    
        }
    
        // 监听document离开松手事件
        @HostListener('document:mouseup', ['$event'])
        onMouseup(ev: any): void {
            ev.stopPropagation();
            // console.log('移除');
            if (this.isDown) {
                document.onmousemove = null;
                document.onmouseup = null;
                this.isDown = false;
                this.changeDownStyle();
            }
        }
    
        // 样式改变
        changeDownStyle(): void {
            if (this.isDown) {
                $(this.element).css({
                    border: '1px solid rgb(0, 229, 255)',
                    background: 'linear-gradient(90deg, #0057cd 0%, #007da4 100%)',
                    cursor: 'move',
                });
            } else {
                $(this.element).css({ border: '1px solid #00aaff', background: 'rgba(0, 42, 127, 0.6)', cursor: 'default', });
            }
        }
    }
    
    

    2.导入module

    import { DraggableDirective } from '../_directives/draggable.directive';
    .
    .
    .
     declarations: [
      DraggableDirective,
    ]
    .
    .
    .
    

    3.页面实现,只需要在拖拽的div上加上appDraggable标签即可

    <div id="myScreenDiv1"  appDraggable>
     
    </div>
    

    相关文章

      网友评论

          本文标题:自定义anglular拖拽指令

          本文链接:https://www.haomeiwen.com/subject/qgglfdtx.html