angular 拖拽

602 阅读1分钟

使用angular 做元素大小的拖拽,做成指令的形式。具体代码如下 1、在初始化的时候,插件文件柄元素,解决直接按照位置计算鼠标位置引起的,dom元素的拉伸过快,元素不能跟着鼠标快速拉伸的问题 2

import {
    Directive,
    ElementRef,
    EventEmitter,
    HostListener,
    Input,
    OnDestroy,
    OnInit,
    Output,
    Renderer2,
} from '@angular/core';

@Directive({
    selector: '[isDragResize]',
})
export class DragresizeDirective implements OnInit, OnDestroy {

    @Input('isDragResize') isDragResize: boolean;
    // dragDirectionRange 可拖拽的方向 八个方向,字符串形式,默认为‘all’,全部
    // 当单独某个方向时可根据right,top,righttop,left,lefttop,leftbottom,bottom,rightbottom进行方向传值
    @Input('dragDirectionRange') dragDirectionRange: string = 'all';
    // minWidth 最小宽度
    @Input('minWidth') minWidth: number;
    // minHeight 最小高度
    @Input('minHeight') minHeight: number;
    // 是否需要定位
    @Input('isPosition') isPosition: boolean;
    // 单次拖拽完成事件,返回最新排序index数据
    @Output() ondragEnd = new EventEmitter();
    public elementLeft = 0;
    public elementTop = 0;
    public originClientX = 0;
    public originClientY = 0;
    public elementWidth = 0;
    public elementHeight = 0;
    public isChanging: Boolean = false;
    public dragDirection: String = '';
    public dragElement: any;

    constructor(private el: ElementRef, private rd: Renderer2) {


    }

    ngOnInit() {
        if (this.isDragResize) {
            this.setDragHandle();
        }
    }

    /**
     * 将对应拖拽方向 插入可拖拽的dom节点
     */
    setDragHandle() {
        if (this.dragDirectionRange === 'all') this.dragDirectionRange = 'right,top,righttop,left,lefttop,leftbottom,bottom,rightbottom';
        const dragDirectionArray = this.dragDirectionRange.split(',');
        let handel = ``;
        dragDirectionArray.map((direction) => {
            handel += `<div class="dragHandel ${direction}Handel" drag-direction="${direction}"></div>`;
        });
        this.el.nativeElement.appendChild(DragresizeDirective.createDocumentFragment(handel));
    }

    /***
     * 根据字符串模板创建dom
     * @param templateString
     */
    static createDocumentFragment(templateString) {
        return document.createRange().createContextualFragment(templateString);
    }

    /**
     * 元素拖拽节点的 鼠标mounseDown事件,记录初始值
     * @param event
     */
    @HostListener('document:mousedown', ['$event'])
    onHandleMouseDown(event) {
         event.preventDefault();
        if (event.target.className && event.target.className.indexOf('dragHandel') > -1) {
            this.dragElement = event.target.parentElement;
            this.isChanging = true;
            this.elementLeft = this.dragElement.offsetLeft;
            this.elementTop = this.dragElement.offsetTop;
            this.originClientX = event.clientX;
            this.originClientY = event.clientY;
            // 获取此时元素的宽高
            this.elementWidth = this.dragElement.offsetWidth;
            this.elementHeight = this.dragElement.offsetHeight;
            this.dragDirection = event.target.getAttribute('drag-direction');
        }
    }

    @HostListener('document:mousemove', ['$event'])
    onHandleMouseMove(event) {
        event.preventDefault();
        if (this.isChanging) {
            const clientX = event.clientX;
            const clientY = event.clientY;
            let width, height, top, left;
            if (this.dragDirection.indexOf('right') > -1) {
                width = this.elementWidth + (clientX - this.originClientX);
            }
            if (this.dragDirection.indexOf('top') > -1) {
                top = this.elementTop + (clientY - this.originClientY);
                top < 0 ? top = 0 : height = this.elementHeight + (this.originClientY - clientY);
            }

            if (this.dragDirection.indexOf('left') > -1) {
                left = this.elementLeft - (this.originClientX - clientX);
                left < 0 ? left = 0 : width = this.elementWidth + (this.originClientX - clientX);
            }

            if (this.dragDirection.indexOf('bottom') > -1) {
                height = this.elementHeight + (clientY - this.originClientY);
            }

            if (width < this.minWidth) width = this.minWidth;
            if (height < this.minHeight) height = this.minHeight;
            if (height) this.dragElement.style.height = height + 'px';
            if (width) this.dragElement.style.width = width + 'px';
            if (this.isPosition) {
                if (left) this.dragElement.style.left = left + 'px';
                if (top) this.dragElement.style.top = top + 'px';
            }

        }
    }

    @HostListener('document:mouseup', ['$event'])
    onHandleMouseUp() {
        // 拖拽完成后传递宽高
        if (this.isChanging) {
            this.ondragEnd.emit({
                width: this.dragElement.offsetWidth,
                height: this.dragElement.offsetHeight,
            });
        }
        this.isChanging = false;
    }

    ngOnDestroy(): void {
        const dragHandleNodeList = document.querySelectorAll('.dragHandel');
        for (let i = 0; i < dragHandleNodeList.length; i++) {
            dragHandleNodeList[i].remove();
        }
    }
}