這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、前言 最近 推特上 一位懂設計和寫代碼的大神一個兩個瀏覽器之間 星球粒子交互的動畫火了, 讓人看了大呼腦洞大開, 瀏覽器竟然還能這麼玩!!! 準備自己也搞搞玩一下 二、實現 原作者的粒子動畫非常炫酷, 但是不是我們本文重點, 我們通過 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
一、前言
最近 推特上 一位懂設計和寫代碼的大神一個兩個瀏覽器之間 星球粒子交互的動畫火了, 讓人看了大呼腦洞大開, 瀏覽器竟然還能這麼玩!!!
準備自己也搞搞玩一下
二、實現
原作者的粒子動畫非常炫酷, 但是不是我們本文重點, 我們通過一個元素在不同視窗的拖拽實現一個可以變幻的例子來學習一下原理, 後續在實現一個稍微複雜的多視窗的小游戲。關於粒子動畫的內容,有興趣的小伙伴可以自己實現
其實實現類似的功能需要的難點並不多,不在乎以下幾個步驟
- 1、 屏幕坐標和視窗坐標轉換
- 2、 跨標簽通訊
1、 先來看第一個點, 獲取屏幕坐標與視窗坐標
// 屏幕坐標轉換為視窗坐標 const screenToClient = (screenX, screenY) => { const clienX = screenX - window.screenX; const clienY = screenY - window.screenY - barHeight(); return [clienX, clienY]; }; // 視窗坐標轉換為屏幕坐標 const clientToScreen = (clienX, clienY) => { const screenX = clienX + window.screenX; const screenY = clienY + window.screenY + barHeight(); return [screenX, screenY]; };
我們先簡單實現一個卡片, 通過url上面傳遞顏色值, 設置定位
在卡片本上設置上點擊拖動等事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>跨標簽通訊</title> </head> <style> .card { width: 300px; height: 300px; background-color: #f00; position: fixed; top: 100px; left: 100px; } </style> <body> 跨標簽通訊 <div class="card">card</div> </body> <script> const barHeight = () => window.outerHeight - window.innerHeight; const cardDom = document.querySelector(".card"); cardDom.style.top = 100 + "px"; cardDom.style.left = 100 + "px"; cardDom.style.background = new URLSearchParams(window.location.search).get("color") || "red"; window.onload = function () { cardDom.onmousedown = function (e) { cardDom.style.cursor = "pointer"; let x = e.pageX - cardDom.offsetLeft; let y = e.pageY - cardDom.offsetTop; window.onmousemove = function (e) { cardDom.style.left = e.clientX - x + "px"; cardDom.style.top = e.clientY - y + "px"; // 發送消息 const clientCoordinateX = e.clientX - x; const clientCoordinateY = e.clientY - y; const ScreenCoordinate = clientToScreen( clientCoordinateX, clientCoordinateY ); sendMessage(ScreenCoordinate); }; window.onmouseup = function () { window.onmousemove = null; window.onmouseup = null; cardDom.style.cursor = "unset"; }; }; }; </script> </html>
2、 跨標簽傳輸
單個元素的拖動就實現了, 很簡單, 如何讓其他標簽的元素也能同步進行, 需要實現跨標簽方案了, 可以參考該文章- 跨標簽頁通信的8種方式
我們就選擇第一種,使用 BroadCast Channel, 使用也很簡單
// 創建 Broadcast Channel const channel = new BroadcastChannel("myChannel"); // 監聽消息 channel.onmessage = (event) => { // 處理接收到的消息 console.log('接收',event) }; // 發送消息 const sendMessage = (message) => { channel.postMessage(message); };只需要在移動時發送消息, 再其他標簽頁就可以接收到值了, 現在關鍵的就是收到發送的坐標點後, 如何處理, 其實關鍵就是要讓幾個視窗的卡片位置轉化到同一個緯度, 讓其再超出瀏覽器的時候,再另一個視窗的同一個位置出現, 所以就需要將視窗坐標轉化成屏幕坐標,發送給其他視窗後, 再轉化成視窗坐標進行渲染即可
// 滑鼠移動發送消息的時候,視窗坐標轉化成屏幕坐標 window.onmousemove = function (e) { cardDom.style.left = e.clientX - x + "px"; cardDom.style.top = e.clientY - y + "px"; const clientCoordinateX = e.clientX - x; const clientCoordinateY = e.clientY - y; const ScreenCoordinate = clientToScreen( clientCoordinateX, clientCoordinateY ); sendMessage(ScreenCoordinate); // 接收消息的時候,屏幕坐標轉化成視窗坐標 channel.onmessage = (event) => { // 處理接收到的消息 const [clienX, clienY] = screenToClient(...event.data); // 不同視窗的卡片要在同一個位置, 要放到同一個坐標系下麵,保持屏幕坐標一致 cardDom.style.left = clienX + "px"; cardDom.style.top = clienY + "px"; };
完整代碼,在最下麵
三、總結
本文通過移動一個簡單的圖形, 在不同瀏覽器之間穿梭變換, 初步體驗了多個瀏覽器之間如何進行交互, 通過拖拽元素,通過跨標簽的通訊, 將當前視窗元素的位置進行發送, 另一個視窗進行實時接收, 然後通過屏幕坐標和視窗坐標進行轉換, 就能實現,從一個瀏覽器拖動到另一個瀏覽器時, 變化元素顏色的功能了, 當然變化背景色只是舉例子, 你也可以變化撲克牌, 變化照片, 這樣看起來像變魔術一樣,非常神奇,看似瀏覽器不同標簽之間沒有聯繫,當以這種方式產生聯繫後, 就會產生很多不可思議的神奇事情。 就像國外大神的多標簽頁的兩個星球粒子, 產生吸引 融合的效果。原理其實是一樣的。
後續前瞻
在通過小demo的學習,知道多瀏覽器的玩法後, 接下來的我們會實現一個更有意思的小游戲,通過瀏覽器化身一個小木棒, 接小球游戲, 先看一下 gif, 接下來的文章會寫具體實現
傳送門