新聞中心
大家好,我卡頌。

創(chuàng)新互聯(lián)專注于企業(yè)全網(wǎng)營(yíng)銷推廣、網(wǎng)站重做改版、雜多網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5、購(gòu)物商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為雜多等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
最近被一段酷炫的量子糾纏效果刷屏了:
原作者是@_nonfigurativ_,一位藝術(shù)家、程序員。
今天簡(jiǎn)單講講他的核心原理。
基礎(chǔ)概念
首先我們需要知道兩個(gè)概念:
- 屏幕坐標(biāo)系,屏幕左上角就是「屏幕坐標(biāo)系」的圓點(diǎn)。
- 窗口坐標(biāo)系,頁(yè)面窗口左上角就是「窗口坐標(biāo)系」的圓點(diǎn)。
如果只用一臺(tái)電腦,不外接屏幕的話,我們會(huì)有:
- 一個(gè)屏幕坐標(biāo)系
- 打開幾個(gè)頁(yè)面,每個(gè)頁(yè)面有各自的窗口坐標(biāo)系
如果外接了屏幕(或外接pad),那么就存在多個(gè)屏幕坐標(biāo)系,這種情況的計(jì)算需要用到「管理屏幕設(shè)備的API」 —— window.getScreenDetails[1],在本文的討論中不涉及這種情況。
當(dāng)我們打開一個(gè)新頁(yè)面窗口,窗口的左上角就是窗口坐標(biāo)系的圓點(diǎn),如果要在頁(yè)面正中間畫個(gè)圓,那圓心的窗口坐標(biāo)系坐標(biāo)應(yīng)該是(window.innerWidth / 2, window.innerHeight / 2)。
對(duì)于一個(gè)打開的窗口:
- 他的左上角相對(duì)于屏幕頂部的距離為window.screenTop。
- 他的左上角相對(duì)于屏幕左邊的距離為window.screenLeft。
所以,我們可以輕松得出圓的圓心在「屏幕坐標(biāo)系」中的坐標(biāo):
位置檢測(cè)
在效果中,當(dāng)打開兩個(gè)頁(yè)面,他們能感知到對(duì)方的位置并作出反應(yīng),這是如何實(shí)現(xiàn)的呢?
當(dāng)前,我們已經(jīng)知道圓心在「屏幕坐標(biāo)系」中的坐標(biāo)。如果打開多個(gè)頁(yè)面,就會(huì)獲得多個(gè)「圓心的屏幕坐標(biāo)系坐標(biāo)」。
現(xiàn)在需要做的,就是讓這些頁(yè)面互相知道對(duì)方的坐標(biāo),這樣就能向?qū)?yīng)的方向做出連接的特效。
同源網(wǎng)站跨頁(yè)面通信的方式有很多,比如:
- Window.postMessage
- LocalStorage、SessionStorage
- SharedWorker
- BroadcastChannel
甚至Cookie也能用于跨頁(yè)面通信(可以在同源的所有頁(yè)面之間共享)。
在這里作者使用的是LocalStorage:
只需要為每個(gè)頁(yè)面生成一個(gè)唯一ID:
const pageId = Math.random().toString(36).substring(2); // 生成一個(gè)隨機(jī)的頁(yè)面ID每當(dāng)將圓心最新坐標(biāo)存儲(chǔ)進(jìn)LocalStorage時(shí):
localStorage.setItem(
pageId,
JSON.stringify({
x: window.screenX,
y: window.screenY,
width: window.innerWidth,
height: window.innerHeight,
})
);在另一個(gè)頁(yè)面通過(guò)監(jiān)聽storage事件就能獲取「對(duì)方圓心的屏幕坐標(biāo)系坐標(biāo)」:
window.addEventListener("storage", (event) => {
if (event.key !== pageId) {
// 來(lái)自另一個(gè)頁(yè)面
const { x, y } = JSON.parse(event.newValue);
// ...
}
});再將對(duì)方「圓心的屏幕坐標(biāo)系坐標(biāo)」轉(zhuǎn)換為自身的「窗口坐標(biāo)系坐標(biāo)」,并在該坐標(biāo)繪制一個(gè)圓,就能達(dá)到類似「窗口疊加后,下面窗口的畫面出現(xiàn)在上面窗口內(nèi)」的效果。
通俗的講,所有頁(yè)面都會(huì)繪制其他頁(yè)面的圓,只是有些圓在頁(yè)面窗口外,看不見罷了。
考慮到頁(yè)面性能,「檢測(cè)圓心的屏幕坐標(biāo)系坐標(biāo)」、「渲染圓」相關(guān)操作可以放到requestAnimationFrame回調(diào)中執(zhí)行。
后記
上述只是該效果的核心原理。要完全復(fù)刻效果,還得考慮:
- 渲染大量粒子(我們示例中用「圓」代替),且多窗口通信時(shí)的性能問題。
- 窗口移動(dòng)時(shí)的阻尼效果。
- 當(dāng)前的實(shí)現(xiàn)是在同一個(gè)屏幕坐標(biāo)系中,如果要跨屏幕實(shí)現(xiàn),需要使用window.getScreenDetails。
不得不感嘆跨界(作者是藝術(shù)家 + 程序員)迸發(fā)的想象力真的不一般。
參考資料
[1]window.getScreenDetails:https://developer.chrome.com/zh/articles/multi-screen-window-placement/。
當(dāng)前文章:談?wù)勍饩W(wǎng)刷屏的量子糾纏效果
分享路徑:http://fisionsoft.com.cn/article/ccojcog.html


咨詢
建站咨詢
