JS效果之《获取鼠标所在区域的容器,区域外都遮罩半透明》

昨天朋友说要实现一个效果,获取鼠标所在区域的容器,区域外都遮罩半透明,起名为专注模式。我们今天来实现一下。
JS效果之《获取鼠标所在区域的容器,区域外都遮罩半透明》_第1张图片

需求分析

  1. 获取鼠标位置,鼠标属于的容器。mouseovermouseoutmousedownmouseupmouseentermouseleavemousemove 这么多事件太容易了。

    1. 但是因为 DOM 结构太多了,其实要的元素有可能是父级祖先级,这里需要实现一个类似于 jquery 的 parants。
  2. 区域外遮罩半透明。这个感觉类似于新手引导的那种效果。

    1. 方案:克隆节点,fixed定位
    2. 方案:box-shadow
    3. 方案:outline
    4. 方案:border,这个就不推荐使用了,上面两个不会影响位置。

功能实现

获取鼠标位置的DOM元素

简直不要太简单。通过事件对象直接拿 e.target

window.addEventListener('mousemove', function(e){
    console.log(e.target)
})

向上递归查找符合条件的DOM元素

parentNode 可以获取到父节点,因为只有一个父节点,比找子节点还少了一个遍历。
实现了一个简单的选择器,只处理了单个的 class、id、tag,想深入的可以看 jquery 的实现。

function findParentAttribute(node, key = ''){
    key = key.trim();
    if(!node) return null;
    if(!key) return node;
    if(node == document) return null;
    switch(key.slice(0,1)){
        case '.': if(node.classList.contains(key.slice(1))){return node}
        case '#': if(node.id == key.slice(1)){return node}
        default: if(node.tagName.toLowerCase() == key){return node}
    }
    if(node.parentNode){
        return findParentAttribute(node.parentNode, key)
    }
    return null;
}

遮罩半透明实现

outline 实现

JS效果之《获取鼠标所在区域的容器,区域外都遮罩半透明》_第2张图片

box-shadow

JS效果之《获取鼠标所在区域的容器,区域外都遮罩半透明》_第3张图片

JS 克隆 DOM

因为原始的 DOM 不能直接修改为 fixed,会造成布局变化,所以我们直接克隆一个,然后将克隆的 fixed 定位。类似于模拟拖拽效果代码。

这个懒得写了,有没有大佬评论区留言呀

完整代码

shadowClass = ['.stream-list__item','div','#app'];
shadowEl = null;
shadowStyleTimeout = 0;
shadowStyle = `.lilnong-shadow{outline: 9999px solid rgba(0,0,0,.5);z-index: 9999999999;transform: translate3d(0px,0px,1px);position: relative;}`;
if(!window.styleEl){
    var styleEl = document.createElement('style');
    styleEl.id = styleEl;
}
styleEl.innerHTML = shadowStyle;
if(!styleEl.parentNode){
    document.head.appendChild(styleEl)
}


window.addEventListener('mouseover', function(e){
    var el = e.target;
    var newEl = null;
    for(let i = 0,l = shadowClass.length; i < l; i++){
        newEl = findParentAttribute(el, shadowClass[i]);
        if(newEl) break;
    }
    if(shadowEl) shadowEl.classList.remove('lilnong-shadow')
    clearTimeout(shadowStyleTimeout);
    shadowStyleTimeout = setTimeout(v=>{
        if(newEl){
            newEl.classList.add('lilnong-shadow')
            shadowEl = newEl;
        }
    },50)
})

function findParentAttribute(node, key = ''){
    //console.log(node, key)
    key = key.trim() || '';
    if(!node) return null;
    if(!key) return node;
    if(node == document) return null;
    switch(key.slice(0,1)){
        case '.': if(node.classList.contains(key.slice(1))){return node}
        case '#': if(node.id == key.slice(1)){return node}
        default: if(node.tagName.toLowerCase() == key){return node}
    }
    if(node.parentNode){
        return findParentAttribute(node.parentNode, key)
    }
    return null;
}

JS效果之《获取鼠标所在区域的容器,区域外都遮罩半透明》_第4张图片

微信公众号:前端linong

clipboard.png

你可能感兴趣的:(javascript,前端,css,css3,html)