通过MutationObserver监听DOM元素,做一个位置随指定元素位置变化而变化的气泡 | ResizeObserver监听元素大小
-
最近需要把时间轴修改成自己想要的样子,需要在时间轴的当前时间条上设置一个气泡,但是没有这个api,于是想到一个办法,通过监听 时间条dom元素,获取时间条的位置,然后创建一个元素当做气泡,这个气泡的位置会随着时间条的位置变化而变化;
1、需要用到MutationObserver 来监听时间条dom元素,
2、用DOM.getBoundingClientRect()方法监听dom相对于窗口的位置;
3、根据时间条的位置,给创建的气泡元素设置位置,从而达到给时间条加气泡的效果;
4、为了简化一些,我用了一个div当做时间条,设置一个定时器让它持续移动。可以模拟出来拖动时间条的场景。
上代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>observer</title> <style> .wrap{ width:400px; height:400px; position: relative; margin-left:200px; } .box{ width: 300px; height:300px; position: absolute; top:0; left:0; background:cadetblue; clip-path: polygon(15px 0, calc(100% - 15px) 0, 100% 15px, 100% calc(100% - 15px), calc(100% - 15px) 100%, 15px 100%, 0 calc(100% - 15px), 0 15px) } .pop{ position: fixed; border:1px solid black; border-radius:4px; padding: 4px; box-shadow: 0px 0px 4px 2px black inset; user-select: none; } </style> </head> <body> <div class="wrap"> <div class="box"></div> </div> <script> let box = document.querySelector(".box"); let add = 1; setInterval(() => { let left = parseInt(getComputedStyle(box).left); console.log(left); if(left > 300 ){ add = -1; } if (left < 0){ add = 1; } box.style.left = `${left + add}px` }, 1000); // 观察者的选项(要观察哪些突变) var config = { attributes: true, childList: false, subtree: false };// 只监听属性发生变化 // 当观察到突变时执行的回调函数 var callback = function(mutationsList) { console.log(mutationsList, 'mutationsList'); mutationsList.forEach(function(item,index){ if (item.type == 'childList') { console.log('有节点发生改变'); } else if (item.type == 'attributes') { let targetleft = item.target.getBoundingClientRect().left; console.log(targetleft,'targetleft'); let date = new Date(); changePop(item.target, ` <div>${date.getYear()}年${date.getMonth() + 1}月${date.getDay()}</div> <span>${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}</span> `) } else if (item.type == 'subtree') { console.log('subtree有变化'); } }); }; // 创建一个链接到回调函数的观察者实例 var observer = new MutationObserver(callback); // 开始观察已配置突变的目标节点 observer.observe(box, config); // 停止观察 //observer.disconnect(); function changePop(parent,innerHTML){ let pop = null; if(!document.querySelector('.pop')){ pop = document.createElement('div'); pop.classList.add('pop') document.body.appendChild(pop); } else { pop = document.querySelector('.pop'); } let position = parent.getBoundingClientRect(); pop.style.left = `${position.left}px`; pop.style.top = `${position.bottom}px`; pop.innerHTML = innerHTML; } </script> </body> </html>
效果:气泡位置会跟着时间条的位置变化而变化
下面简单说一下ResizeObserver API的使用,这个方法是监听元素的大小改变,不用通过window.resize来监听窗口改变来达到目的,有些时候只监听window.resize也是达不到目的的,因为我们可能用js来改变某一个元素的宽高,所以用ResizeObserver方法来监听会更加方便,不过这个API目前是实验阶段,在chrome浏览器已经支持
文档地址:https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver
<textarea id="main"></textarea> <script> // javascript let mainEl = document.querySelector('#main') const resizeObserver = new ResizeObserver(entries => { console.log(entries, 'entries'); for (let entry of entries) { console.log(entry.contentRect, 'contentRect'); entry.target.style.borderRadius = Math.max(0, 250 - entry.contentRect.width) + 'px'; } }); resizeObserver.observe(mainEl); // 取消某个元素监听 //resizeObserver.unobserve(mainEl) // 取消全部元素监听 //resizeObserver.disconnect()
拖动富文本框,监听到实时的大小。
-