Vue指令实现dialog组件拖拽

66 阅读1分钟

`js

import Vue from 'vue';

Vue.directive('dialogDrag', { bind(el) { // dialog原始位置

    // 当前宽高
    let nowWidth = 0;
    let nowMarginRight = 0;
    let nowMarginLeft = 0;
    document.ondragstart = function() {
        return false;
    };
    // 获取弹框头部(这部分可双击全屏)
    const dialogHeaderDom = el.querySelector('.el-dialog__header');
    // 弹窗
    const dialogDom = el.querySelector('.el-dialog');
    const titleDom = el.querySelector('.el-dialog__title');

    let bodyShow = true;

    // 给弹窗加上overflow auto;不然缩小时框内的标签可能超出dialog;
    dialogDom.style.overflow = 'auto';
    // 清除选择头部文字效果
    dialogHeaderDom.onselectstart = new Function('return false');
    // 头部加上可拖动cursor
    dialogHeaderDom.style.cursor = 'move';

    titleDom.style.overflow = 'hidden';
    titleDom.style.textOverflow = 'ellipsis';
    titleDom.style.whiteSpace = 'nowrap';

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = dialogDom.currentStyle || window.getComputedStyle(dialogDom, null);

    const moveDown = e => {
        // 鼠标按下,计算当前元素距离可视区的距离
        const disX = e.clientX - dialogHeaderDom.offsetLeft;
        const disY = e.clientY - dialogHeaderDom.offsetTop;

        // 获取到的值带px 正则匹配替换
        let styL, styT;

        // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
        if (sty.left.includes('%')) {
            styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
            styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
        } else {
            styL = +sty.left.replace(/\px/g, '');
            styT = +sty.top.replace(/\px/g, '');
        }

        const dialogMove = e => {
            const l = e.clientX - disX;
            const t = e.clientY - disY;
            dialogDom.style.left = `${l + styL}px`;
            dialogDom.style.top = `${t + styT}px`;
        };

        document.addEventListener('mousemove', dialogMove);

        document.onmouseup = function() {
            document.removeEventListener('mousemove', dialogMove);
            document.onmouseup = null;
        };
    };
    // dialogHeaderDom.onmousedown = moveDown;
    dialogHeaderDom.addEventListener('mousedown', moveDown);
    // 右上角最小化按钮
    const resizeButtonDom = document.createElement('div');
    dialogHeaderDom.appendChild(resizeButtonDom);
    // 在标题右边加上一个16px-16px的控制块
    resizeButtonDom.style.cursor = 'pointer';
    resizeButtonDom.className = 'el-icon-minus';
    resizeButtonDom.style.position = 'absolute';
    resizeButtonDom.style.height = '16px';
    resizeButtonDom.style.width = '16px';
    resizeButtonDom.style.right = '48px';
    resizeButtonDom.style.color = '#909399';
    resizeButtonDom.style.top = '22px';
    const clickResize = () => {
        const dialogBodyDom = el.querySelector('.el-dialog__body');
        const dialogBox = document.querySelector('.el-dialog__wrapper.f-magnifier-dialog');

        const modalDom = document.querySelector('.v-modal');
        if (bodyShow == true) {
            bodyShow = false;
            nowWidth = dialogDom.style.width;
            nowMarginLeft = dialogDom.style.marginLeft;
            nowMarginRight = dialogDom.style.marginRight;
            dialogDom.style.width = '300px';
            dialogDom.style.position = 'fixed';
            dialogBodyDom.style.display = 'none';
            titleDom.style.display = 'inline-block';
            titleDom.style.width = '200px';
            dialogDom.style.top = 'unset';
            dialogDom.style.right = '18px';
            dialogDom.style.bottom = '0px';
            dialogDom.style.left = 'unset';
            if (dialogBox?.style) {
                dialogBox.style.width = '0px';
            }
            if (modalDom?.style) {
                modalDom.style.display = 'none';
            }
            dialogDom.style.marginLeft = '0px';
            dialogDom.style.marginRight = '0px';
            resizeButtonDom.className = 'el-icon-rank';
            resizeButtonDom.style.transform = 'rotate(45deg)';
            dialogHeaderDom.removeEventListener('mousedown', moveDown);
        } else {
            bodyShow = true;
            dialogDom.style.width = nowWidth;
            titleDom.style.width = '240px';
            dialogDom.style.position = 'relative';
            dialogBodyDom.style.display = 'inherit';
            titleDom.style.display = 'inline';
            dialogDom.style.left = '0';
            dialogDom.style.top = '0';
            dialogDom.style.right = 'unset';
            dialogDom.style.bottom = 'unset';
            if (dialogBox?.style) {
                dialogBox.style.width = 'unset';
            }
            if (modalDom?.style) {
                modalDom.style.display = 'unset';
            }
            dialogDom.style.marginLeft = nowMarginLeft;
            dialogDom.style.marginRight = nowMarginRight;
            resizeButtonDom.className = 'el-icon-minus';
            resizeButtonDom.style.transform = 'none';
            dialogHeaderDom.addEventListener('mousedown', moveDown);
        }
    };
    resizeButtonDom.addEventListener('click', clickResize);
}

});

`