昨天朋友說要實現一個效果,獲取鼠標所在區域的容器,區域外都遮罩半透明,起名爲專一模式。咱們今天來實現一下。
前端
獲取鼠標位置,鼠標屬於的容器。mouseover
,mouseout
,mousedown
,mouseup
,mouseenter
,mouseleave
,mousemove
這麼多事件太容易了。node
elementsFromPoint
獲取座標下的 DOM 元素e.path
獲取路徑區域外遮罩半透明。這個感受相似於新手引導的那種效果。jquery
box-shadow
outline
border
,這個就不推薦使用了,上面兩個不會影響位置。簡直不要太簡單。經過事件對象直接拿 e.target
微信
window.addEventListener('mousemove', function(e){ console.log(e.target) })
parentNode
能夠獲取到父節點,由於只有一個父節點,比找子節點還少了一個遍歷。
實現了一個簡單的選擇器,只處理了單個的 class、id、tag,想深刻的能夠看 jquery 的實現。app
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; }
通過評論區的哥們提醒,能夠用 document.elementsFromPoint(e.clientX, e.clientY)
來獲取全部的,就不用遞歸了dom
忽然又想到可使用 e.path 來直接獲取觸發路徑,省去遞歸。佈局
由於原始的 DOM 不能直接修改成 fixed,會形成佈局變化,因此咱們直接克隆一個,而後將克隆的 fixed 定位。相似於模擬拖拽效果代碼。spa
這個懶得寫了,有沒有大佬評論區留言呀。3d
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; }
評論區一哥們提醒還有 elementsFromPoint
和 elementFromPoint
來實現,獲取鼠標位置的 DOM 元素code
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){ if(shadowEl) shadowEl.classList.remove('lilnong-shadow') var els = document.elementsFromPoint(e.clientX, e.clientY); shadowClass.every(selectorKey=>{ var el = els.find(el=>{ keySlice = [selectorKey.slice(0,1),selectorKey.slice(1)] switch(keySlice[0]){ case '.': if(el.classList.contains(keySlice[1])){return el} case '#': if(el.id == keySlice[1]){return el} default: if(el.tagName.toLowerCase() == selectorKey){return el} } return false; }) if(el){ el.classList.add('lilnong-shadow') shadowEl = el; return false } return true }) })