本文不是技术文章,只是简单记录最近妇联4的热播,先剧透两个亮点。前两天在谷歌搜索看到一个彩蛋,搜索Thanos或者thanos,点击右边的无限手套触发彩蛋,打响指,扫掉一半搜索结果条目。消失的效果和电影里的差不多。首先分析一下这个彩蛋,主要包括点击手套时动画效果消失的搜索项的粒子效果。接下来从以下几个方面入手:html页面DOM转canvas粒子效果。其他还有音效,页面平滑滚动等,搜索页面无法访问,因为服务器使用的是国内阿里云。然后我打算拿起百度的搜索页面,使用PHP程序。我知道有file_get_content和cURL函数可以获取页面代码。虽然拿到了页面代码,但是只要搜索到搜索结果的DOM,使用正则表达式比较麻烦。找到phpQuery库,可以像jQuery操作一样获取指定的DOM,类似于Node.js的cheerio包。但是百度的页面样式类是动态的,还要输出整个样式内容,而且很多图片估计已经处理过了,未经允许不能显示,所以放弃了。然后他拿起斗鱼的直播列表页,返回了一堆乱码,力气就认了。最后选择了一个类似企鹅电竞直播列表页面,页面就完成了。DOM转canvas前端有html2canvas和dom-to-image两个库,可以将页面的指定元素转为canvas或者图片。html2canvas比较有名,我早期的前端截图功能也是用这个库(https://imusic.github.io/clip/),但是对CSS3处理不好,后来发现dom-to-image库,它可以更好地处理CSS3并且更小,所以我用这个库(https://demo.vczhan.com/clip/)替换了它。但是因为要转换的内容中有跨域的图片,canvas对此有限制,我们需要对图片进行代理。dom-to-image库没有提供相关代理插件,最终使用html2canvas库。页面上没有复杂的元素,最近更新了这个库,更好的支持CSS3。作者也提供了Python版和Node.js版两种语言的agent,不过我选择了别人写的PHP版。前端只需要配置相关参数即可。服务端会在文件目录下新建一个缓存目录用来存放图片,返回给前端渲染到画布上。(不知道能不能改成输出base64或者blob数据,而不是存储图片文件)html2canvas(node,{proxy:'html2canvasproxy.php'}).then(canvas=>{//dostuff})particleeffectparticleeffect中比较难的部分是如何将每个参数调整到合适的值,并保证动画不卡顿。其实js计算过程不会让动画卡顿,主要瓶颈在渲染阶段。渲染部分本来是直接通过粒子遍历绘制的,但是因为粒子比较多,所以动画看起来有点卡。渲染(){上下文。clearRect(0,0,sw,sh)让粒子=this。particlesfor(leti=0,particle;particle=particles[i++];){if(particle.state==='dead')continuecontext.save()context.translate(particle.x,particle.y)上下文.fillStyle=particle.colorcontext.globalAlpha=particle.alphacontext.beginPath()context.fillRect(0,0,1,1)context.restore()}}之后每次渲染的时候,先获取图像数据空白画布,然后遍历粒子,将rgba添加到图像数据对应的位置,最后将图像数据放回画布上。render(){//context.clearRect(0,0,sw,sh)让粒子=this.particlesconstimageData=context.createImageData(sw,sh)constbuffer32=newUint32Array(imageData.data.buffer)for(leti=0,particle;particle=particles[i++];){if(particle.state==='dead')continueconst{x,y,color:{r,g,b},alpha:a}=粒子constpos=y*sw+xbuffer32[pos]=r|(g<<8)|(b<<16)|(a<<24)}context.putImageData(imageData,0,0)}Google那个页面是用了多个画布,可以参考下面的粒子https://codepen.io/birjolaxew...其他都是一些细节调整,比如点击手套的转场动画,加上音效,要慢慢调整转场时间和延迟,让动画和音效对应得恰到好处。当某个DOM消失时,应添加音效,页面平滑滚动,使其位于屏幕中央。您可以直接使用scrollIntoView方法。node.scrollIntoView({behavior:'smooth',block:'center'})的素材可以从google彩蛋页面中提取,还有其他的细节就不一一赘述了。最后放这个demo
