自定义指令 包含滚动触发单独弹框 自由

Vue.directive(‘dragx’,{
inserted:function(el,binding,vnode,oldVnode){
// 默认参数
let defaultOpts = {
//可以拉伸 w向左 n向上 e向右 s向下 ne右上 sw左下 se右下 nw左上 all就代表全部
dragDirection:‘n, e, s, w, ne, se, sw, nw, all’,
dragContainerId:’’, //在哪个容器内可以移动 需要填ID
dragBarClass:’’, // 类选择器 希望按哪里进行拖拽就把那个类名字填上
resizeEdge:10,
canDrag:true,//是否可以移动 默认可以
canResize:true,//是否可以改变大小 默认可以
minWidth:0,//最小宽度
minHeight:0,//最小高度
maxWidth:0,//最大拉伸至多少时会恢复最小宽度 默认0 即不恢复
maxHeight:0,//最大拉伸至多少时会恢复最小高度
previousId:’’,//绑定元素的上一个id
nextId:’’,//绑定元素的下一个id 一般填这个 如果他是第一个元素 则填上一个的id
scrollDiv:false,//是否是滚动悬浮元素 默认不是
clickId:’’,//点击哪个按钮会让他回到原来位置
leftDrag:true,
rightDrag:true,
topDrag:true,
bottomDrag:true
};
let isMove = false;
binding.value = binding.value || {};
let cfg = Object.assign({},defaultOpts,binding.value);
let stickStartPos = {mouseX:0,mouseY:0,x:0,y:0,w:0,h:0};
let divHeight = el.offsetHeight;//初始的高度 保证悬浮之后不变形
let divWidth = el.offsetWidth;//初始的宽度 保证悬浮之后不变形
let scroll = true;//保证滚动的判断方法只执行一次
let scrollBox = true;//保证盒子在不悬浮的时候 不会出现拖动拉伸图标
let drag = el.parentNode;//绑定盒子的父元素
let clickBox;
let scrollTop;
if(cfg.scrollDiv){
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.vueClickOutside = handleScroll;
//绑定滚动事件监听
window.addEventListener(‘scroll’,handleScroll,true);
scrollBox = false;
scrollTop = el.getBoundingClientRect().top - drag.getBoundingClientRect().top;
}
//滚动
function handleScroll(){
let constraintDom;
if(cfg.previousId !== ‘’ && cfg.nextId === ‘’){
constraintDom = document.querySelector("#" + cfg.previousId);
if(constraintDom.offsetHeight > constraintDom.getBoundingClientRect().top && el.getBoundingClientRect().top >= 0 && constraintDom.getBoundingClientRect().bottom - drag.getBoundingClientRect().top > 0){
el.style.position = ‘static’;
scrollBox = false;
el.style.width = divWidth + ‘px’;
el.style.height = divHeight + ‘px’;
scroll = true;
}
}
if(cfg.nextId !== ‘’){
constraintDom = document.querySelector("#" + cfg.nextId);
if(constraintDom.getBoundingClientRect().top - drag.getBoundingClientRect().top > 0){
el.style.position = ‘static’;
el.style.width = divWidth + ‘px’;
el.style.height = divHeight + ‘px’;
scroll = true;
scrollBox = false;
}
}
if(el.getBoundingClientRect().top - drag.getBoundingClientRect().top < 0 && scroll){
let box = document.querySelector("#" + cfg.dragContainerId);
let constraintRect = box.getBoundingClientRect();
el.style.position = ‘absolute’;
el.style.left = constraintRect.width - (divWidth + 10) + ‘px’;
el.style.top = constraintRect.height - (divHeight + 10) + ‘px’;
scrollBox = true;
el.style.width = divWidth + ‘px’;
el.style.height = divHeight + ‘px’;
scroll = false;
clickBox = document.querySelector("#" + cfg.clickId);
clickBox.addEventListener(‘click’,function(){
if(el.style.position === ‘absolute’){
drag.scrollTop = scrollTop;
}
el.style.position = ‘static’;
el.style.width = divWidth + ‘px’;
el.style.height = divHeight + ‘px’;
scroll = true;
scrollBox = false;
},{once:true});
}
}
//获取可以移动的最大范围
function calcResizeLimitation(data){
let minw = cfg.minWidth;
let minh = cfg.minHeight;
let width = data.width;
let height = data.height;
let bottom = data.bottom;
let top = data.top;
let left = data.left;
let right = data.right;
let parentLim = 0;
let limits = {
minLeft:parentLim,
maxLeft:left + (width - minw),
minRight:parentLim,
maxRight:right + (width - minw),
minTop:parentLim,
maxTop:top + (height - minh),
minBottom:parentLim,
maxBottom:bottom + (height - minh)
};
return limits;
}
// 获取目标元素 resize方向
function getDirection(e){
let el = e.currentTarget;
let dir = ‘’;
let rect = el.getBoundingClientRect();
let win = el.ownerDocument.defaultView;
let offset = {
top:rect.top + win.pageYOffset,
left:rect.left + win.pageXOffset,
right:rect.right + win.pageXOffset,
bottom:rect.bottom + win.pageYOffset
}
if(e.pageY > offset.top && e.pageY < offset.top + cfg.resizeEdge){
dir += ‘n’;
}else if(e.pageY < offset.bottom && e.pageY > offset.bottom - cfg.resizeEdge){
dir += ‘s’;
}
if(e.pageX > offset.left && e.pageX < offset.left + cfg.resizeEdge){
dir += ‘w’;
}else if(e.pageX < offset.right && e.pageX > offset.right - cfg.resizeEdge){
dir += ‘e’;
}
if(binding.value){
let directions = cfg.dragDirection.split(’,’);
for(let i = 0; i < directions.length; i++){
let handle = directions[i].replace(/(^\s*)|(\s*$)/g,’’);
if(handle === ‘all’ || handle === dir){
return dir;
}
}
}
return ‘’;
}
//解决拖动会选中文字的问题
document.onselectstart = function(){
return false;
};
el.onmousemove = function(e){
if(cfg.dragBarClass.length > 0 && e.target.classList.contains(cfg.dragBarClass) && cfg.canDrag && scrollBox){
el.style.cursor = ‘move’;
return;
}
let dir = getDirection(e);
if(dir !== ‘’ && cfg.canResize && scrollBox){
el.style.cursor = dir + ‘-resize’;
return;
}
el.style.cursor = ‘’;
}
el.onmouseleave = function(e){
el.style.cursor = ‘’;
}
el.onmousedown = function(e){
let content = document.querySelector("#" + cfg.dragContainerId);
let dragDiv = el;
dragDiv.startX = e.clientX - dragDiv.offsetLeft;
dragDiv.startY = e.clientY - dragDiv.offsetTop;
isMove = false;
if(cfg.dragBarClass.length > 0 && e.target.classList.contains(cfg.dragBarClass) && cfg.canDrag && scrollBox){
isMove = true;
document.body.style.cursor = ‘move’;
}
let style = window.getComputedStyle(el);

        function getStyleNumValue(key){
            return parseInt(style.getPropertyValue(key),10);
        }

        let rect = el.getBoundingClientRect();
        let data = {
            dragWidthMax:false,
            dragHeightMax:false,
            width:getStyleNumValue("width"),
            height:getStyleNumValue("height"),
            left:getStyleNumValue("left"),
            top:getStyleNumValue("top"),
            right:getStyleNumValue("right"),
            bottom:getStyleNumValue("bottom"),
            borderLeft:getStyleNumValue("border-left-width"),
            borderTop:getStyleNumValue("border-top-width"),
            borderRight:getStyleNumValue("border-right-width"),
            borderBottom:getStyleNumValue("border-bottom-width"),
            deltX:e.pageX - rect.left,
            deltY:e.pageY - rect.top,
            startX:rect.left,
            startY:rect.top
        };
        let dragLeft = data.left;
        let dragTop = data.top;
        //在鼠标按下的时候进行赋值
        stickStartPos.mouseX = typeof e.pageX !== 'undefined' ? e.pageX : e.touches[0].pageX;
        stickStartPos.mouseY = typeof e.pageY !== 'undefined' ? e.pageY : e.touches[0].pageY;
        stickStartPos.left = data.left;
        stickStartPos.right = data.right;
        stickStartPos.top = data.top;
        stickStartPos.bottom = data.bottom;
        let limits = calcResizeLimitation(data);
        let dir = getDirection(e);
        if(dir === '' && !isMove) return;
        // 创建遮罩
        let mask = document.createElement("div");
        mask.style.cssText = "position:absolute;top:0px;bottom:0px;left:0px;right:0px;";
        document.body.appendChild(mask);
        document.onmousemove = function(edom){
            let pageX = typeof edom.pageX !== 'undefined' ? edom.pageX : edom.touches[0].pageX;
            let pageY = typeof edom.pageY !== 'undefined' ? edom.pageY : edom.touches[0].pageY;
            let delta = {
                x:(stickStartPos.mouseX - pageX) / 1,
                y:(stickStartPos.mouseY - pageY) / 1
            };
            let newTop = stickStartPos.top - delta.y;
            let newBottom = stickStartPos.bottom + delta.y;
            let newLeft = stickStartPos.left - delta.x;
            let newRight = stickStartPos.right + delta.x;
            let constraintDom = document.querySelector("#" + cfg.dragContainerId);
            let constraintRect = constraintDom.getBoundingClientRect();
            if(cfg.canResize && scrollBox){
                if(dir.indexOf("w") > -1 && cfg.leftDrag){
                    if(limits.minLeft !== null && newLeft < limits.minLeft){
                        newLeft = limits.minLeft;
                    }else if(limits.maxLeft !== null && limits.maxLeft < newLeft){
                        newLeft = limits.maxLeft;
                    }
                    data.left = newLeft;
                    data.width = constraintRect.width - data.left - data.right - data.borderLeft - data.borderRight;
                    if(data.width > cfg.maxWidth && cfg.maxWidth > 0){
                        data.width = cfg.minWidth;
                        data.left = dragLeft;
                        data.dragWidthMax = true;
                        cfg.leftDrag = false;
                    }
                    el.style.left = data.left + 'px';
                    el.style.width = data.width + 'px';
                }
                if(dir.indexOf("n") > -1 && cfg.topDrag){
                    if(limits.minTop !== null && newTop < limits.minTop){
                        newTop = limits.minTop;
                    }else if(limits.maxTop !== null && limits.maxTop < newTop){
                        newTop = limits.maxTop;
                    }
                    data.top = newTop;
                    data.height = constraintRect.height - data.top - data.bottom - data.borderTop - data.borderBottom;
                    if(data.height > cfg.maxHeight && cfg.maxHeight > 0){
                        data.height = cfg.minHeight;
                        data.top = dragTop;
                        data.dragHeightMax = true;
                        cfg.topDrag = false;
                    }
                    el.style.top = data.top + 'px';
                    el.style.height = data.height + 'px';
                }
                if(dir.indexOf("s") > -1 && cfg.bottomDrag){
                    if(limits.minBottom !== null && newBottom < limits.minBottom){
                        newBottom = limits.minBottom;
                    }else if(limits.maxBottom !== null && limits.maxBottom < newBottom){
                        newBottom = limits.maxBottom;
                    }
                    data.bottom = newBottom;
                    data.height = constraintRect.height - data.top - data.bottom - data.borderTop - data.borderBottom;
                    if(data.height > cfg.maxHeight && cfg.maxHeight > 0){
                        data.height = cfg.minHeight;
                        data.dragHeightMax = true;
                        cfg.bottomDrag = false;
                    }
                    el.style.height = data.height + 'px';
                }
                if(dir.indexOf("e") > -1 && cfg.rightDrag){
                    if(limits.minRight !== null && newRight < limits.minRight){
                        newRight = limits.minRight;
                    }else if(limits.maxRight !== null && limits.maxRight < newRight){
                        newRight = limits.maxRight;
                    }
                    data.right = newRight;
                    data.width = constraintRect.width - data.left - data.right - data.borderLeft - data.borderRight;
                    if(data.width > cfg.maxWidth && cfg.maxWidth > 0){
                        data.width = cfg.minWidth;
                        data.dragWidthMax = true;
                        cfg.rightDrag = false;
                    }
                    el.style.width = data.width + 'px';
                }
            }
            // 处理组件 移动
            if(isMove && cfg.canDrag && scrollBox){
                dragDiv.style.left = edom.clientX - dragDiv.startX + "px";
                dragDiv.style.top = edom.clientY - dragDiv.startY + "px";
                data.left = edom.clientX - dragDiv.startX;
                data.top = edom.clientY - dragDiv.startY;
                if(edom.clientX - dragDiv.startX <= 0){
                    data.left = 0;
                    dragDiv.style.left = 0 + "px";
                }
                if(edom.clientY - dragDiv.startY <= 0){
                    data.top = 0;
                    dragDiv.style.top = 0 + "px";
                }
                if(edom.clientX - dragDiv.startX >= content.offsetWidth - dragDiv.offsetWidth){
                    data.left = content.offsetWidth - dragDiv.offsetWidth;
                    dragDiv.style.left = content.offsetWidth - dragDiv.offsetWidth + "px";
                }
                if(edom.clientY - dragDiv.startY >= content.offsetHeight - dragDiv.offsetHeight){
                    data.top = content.offsetHeight - (dragDiv.offsetHeight + 2);
                    dragDiv.style.top = content.offsetHeight - (dragDiv.offsetHeight + 2) + "px";
                }
            }
            el.dispatchEvent(new CustomEvent('bindUpdate',{detail:data}));
        }
        document.onmouseup = function(e){
            document.body.style.cursor = '';
            document.onmousemove = null;
            document.onmouseup = null;
            isMove = false;
            cfg.leftDrag = true;
            cfg.rightDrag = true;
            cfg.topDrag = true;
            cfg.bottomDrag = true;
            document.body.removeChild(mask);
        }
        document.body.style.cursor = dir + '-resize';
    }
},
unbind:function(el,binding,vnode,oldVnode){
    window.removeEventListener('scroll',el.__vueClickOutside__,true);
    delete el.__vueClickOutside__;
}

});

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值