|
最近前端实现的量子纠缠在网络上火了起来,作者bgstaal的推文:效果如下:量子纠缠那我们一起来看下什么是量子纠缠,以及前端是如何实现的。什么是量子纠缠?在量子力学里,当几个粒子在彼此相互作用后,由于各个粒子所拥有的特性已综合成为整体性质,无法单独描述各个粒子的性质,只能描述整体系统的性质,则称这现象为量子缠结或量子纠缠。量子纠缠是一种奇怪的量子力学现象,处于纠缠态的两个量子不论相距多远都存在一种关联,其中一个量子状态发生改变,另一个的状态会瞬时发生相应改变。前端如何来实现?作者bgstaal在github上开源了一个项目,r说明如何使用 Three.js 和 localStorage 在多个窗口中设置3D场景。一起来看下代码如何实现的。首先,从 Github 上克隆multipleWindow3dScene项目:gitclonehttps://github.com/bgstaal/multipleWindow3dScene.git接下来,通过 vscode 中的 Live Server, 启动该项目,并在浏览器中打开项目主页http://127.0.0.1:5500/index.html。效果如下:展示效果现在我们看下项目目录,如下图所示:index.html:设置 HTML 结构的入口点。main.js:使用 Three.js 初始化 3D 场景,管理窗口的调整大小事件,并根据窗口交互更新场景。three.r124.min.js:用于 3D 图形渲染的 Three.js 库的压缩版本。WindowManager.js:处理多个浏览器窗口的生命周期,包括创建、同步和删除。它使用 localStorage 来维护跨窗口的状态。index.htmlindex.html:设置 HTML 结构的入口点,引入了压缩后的three.js以及main.js。下来我们先看下main.js。main.js定义了存放3d场景以及时间变量,在网站加载成功,页面可见时,则执行初始化init函数,设置场景,窗口管理器等相关配置。init函数init 函数负责设置场景、窗口管理器、调整渲染器大小以适应窗口,并开始渲染循环。functioninit(){initialized=true;//addashorttimeoutbecausewindow.offsetXreportswrongvaluesbeforeashortperiodsetTimeout(()=>{setupScene();setupWindowManager();resize();updateWindowShape(false);render();window.addEventListener('resize',resize);},500)}这里添加了一个定时器,主要是因为window.offsetX在短时间内会返回错误的值。setupScene函数创建了相机、场景、渲染器和3D世界对象,并将渲染器的DOM元素添加到文档体中。//设置场景functionsetupScene(){//创建正交相机camera=newt.OrthographicCamera(0,0,window.innerWidth,window.innerHeight,-10000,10000);//设置相机位置camera.position.z=2.5;near=camera.position.z-.5;far=camera.position.z+0.5;//创建场景scene=newt.Scene();scene.background=newt.Color(0.0);scene.add(camera);//创建渲染器renderer=newt.WebGLRenderer({antialias:true,depthBuffer:true});renderer.setPixelRatio(pixR);//创建对象3Dworld=newt.Object3D();scene.add(world);//设置渲染器的idrenderer.domElement.setAttribute("id","scene");//将渲染器添加到body中document.body.appendChild(renderer.domElement);}窗口管理器的设置通过setupWindowManager函数完成,它实例化WindowManager,并定义窗口形状变化和窗口改变的回调函数。窗口形状变化用于跟踪和反应窗口位置的移动。窗口改变的回调函数用于更新场景中的立方体数量。//创建一个WindowManager实例functionsetupWindowManager(){windowManager=newWindowManager();//设置窗口形状改变回调函数windowManager.setWinShapeChangeCallback(updateWindowShape);//设置窗口改变回调函数windowManager.setWinChangeCallback(windowsUpdated);//hereyoucanaddyourcustommetadatatoeachwindowsinstance//在这里,您可以向每个窗口实例添加自定义元数据letmetaData={foo:"bar"};//thiswillinitthewindowmanagerandaddthiswindowtothecentralisedpoolofwindows//这将初始化窗口管理器并将此窗口添加到集中的窗口池中windowManager.init(metaData);//callupdatewindowsinitially(itwilllaterbecalledbythewinchangecallback)//调用updateWindows函数windowsUpdated();}//当窗口更新时调用该函数functionwindowsUpdated(){//更新立方体数量updateNumberOfCubes();}//更新立方体数量functionupdateNumberOfCubes(){//获取所有窗口letwins=windowManager.getWindows();//removeallcubes//移除所有立方体cubes.forEach((c)=>{world.remove(c);})//重新初始化立方体数组cubes=[];//addnewcubesbasedonthecurrentwindowsetup//根据当前窗口设置添加新的立方体for(leti=0;i
|
|