前言前阵子忙着找工作。在面试过程中,我遇到了一个有趣的问题。新手引导动画的实现方式我列举了尽可能多的。昨天总结了一下,实现了4种。源代码在最后。如果想直接看到结果,可以拖到最后看到。这里假设所有的弹出层都是基于页面上的原始元素来实现复制目标内容的具体步骤:使用getBoundingClientRect获取目标内容的显示位置,复制一个目标内容,然后设置Relative定位,定位数据在上一步中获取,复制的内容下面要设置z-index高一点,还要加一层半透明遮罩层。核心代码:lettarget=document.querySelector('.mid-center')letpos=target.getBoundingClientRect()letclone=target.cloneNode(true)clone.style.position='fixed'clone.style.left=pos.leftclone.style.top=pos.topclone.style.width=pos.widthclone.style.height=pos.heightclone.style.zIndex=100document.body.appendChild(clone)比较普通的实现方式的优缺点是很普通,没有什么特别之处。第二种实现使用box-shadow具体步骤:将目标对象的box-shadow设置为一个比较大的半透明值,将目标对象的位置设置为相对核心代码:lettarget=document.querySelector('.mid-center')target.style.boxShadow='0004000pxrgba(0,0,0,0.85)'target.style.position='relative'这里设置了position:relative,这样box-shadow阴影就不会被遮挡由父容器。如果不设置,box-shadow会显示不完整的优缺点优点:实现简单易懂缺点:box-shadow是一个比较耗性能的属性,依赖于position:relative我不知道会不会有覆盖不了的问题实现3使用html2canvas在半透明画布上绘制目标内容。其中具体步骤:使用getBoundingClientRect获取目标内容的显示位置使用html2canvas将目标内容绘制到上一步获取的指定位置和Size核心代码:lettarget=document.querySelector('.mid-center')letpos=target.getBoundingClientRect()letw=~~pos.widthleth=~~pos.heightletcanvas=document.querySelector('#canvas')canvas.width=document.documentElement.clientWidthcanvas.height=document.documentElement.clientHeightletctx=canvas.getContext("2d");canvas.style.display='block'html2canvas(target,{width:w,height:h,}).then((cvs)=>{ctx.drawImage(cvs,pos.left,pos.top)})需要注意的是canvas.width和canvas.height需要手动设置,否则默认是300*150,所以如果在样式中设置宽高,它会导致画布被拉伸。优缺点优点:性能应该相对好一些(如果html2canvas性能太差的话),用canvas实现的时候不容易碰到各种层次遮挡或者显示不全的问题。缺点:实现方式比较繁琐,需要借助外部工具实现其他四个元素设置为半透明。然后给身体添加黑色背景色。具体步骤:给整个文档的最外层元素,设置黑色背景色遍历整个文档,设置非目标内容和非目标内容的父容器为半透明核心代码:functionshowGuidance(){letmain=document.querySelector('.main')main.className+='darkBackGround'setOpticity(main)}functionsetOpticity(element){让doms=Array.from(element.children)||[]lethasMatched=falsefor(letelofdoms){if(!el.className.match(/mid-center/i)&&el.children.length){hasMatched=setOpticity(el)if(!hasMatched)el.className+='halfTransparent'}elseif(el.className.match(/mid-center/i)){hasMatched=true}else{el.className+='halfTransparent'}}returnhasMatched}如果你不小心设置了目标元素的父元素要半透明,即使目标元素没有设置为半透明,它也会变成透明的,因为父元素里面的所有内容都会透明优缺点优点:我觉得没有优点缺点:批量操作dom,当dom元素较多时,性能极差最后,以上所有实现方式都是基于最简单的实现方式,没有考虑一些特殊情况(如:resize、animation等。)附上源码
