?效果:
三個球
源碼:?
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>三個球</title>
</head>
<body><div id="alert1" style="white-space:pre-wrap;"></div><br /><div id="alert2" style="white-space:pre-wrap;"></div><canvas id="canvas1" style="position:absolute;left:0;top:0;"></canvas> <script>const alert1 = document.getElementById('alert1');const alert2 = document.getElementById('alert2');const canvas1 = document.getElementById('canvas1');const ctx = canvas1.getContext('2d');const keys = getOtherKeys(); // 獲取其它窗口的storage keysconst key = keys.length == 0 ? 1 : keys.at(-1) + 1; // 自增最大的key序號,定義自己窗口storage keyconst color = ['red', 'blue', 'green'][key % 3]; // 獲取圓顏色// 窗口關閉時刪除自己窗口storagewindow.onunload = function () {localStorage.removeItem(key);}function getOtherKeys() {const keys = [];for (let i = 0; i < localStorage.length; i++) {const k = Number(localStorage.key(i));!isNaN(k) && keys.push(k);}return keys.sort((a, b) => a - b);}function draw() {const { clientWidth, clientHeight } = document.body; // 獲取body高寬const { screenX, screenY } = window; // 獲取瀏覽器相對屏幕坐標const barHeight = window.outerHeight - window.innerHeight; // 獲取瀏覽器body頂部地址欄高度// 記錄logalert1.textContent = JSON.stringify({ key, clientWidth, clientHeight, screenX, screenY, barHeight }, '', 2);// 設置canvas為整個body高寬,鋪滿bodycanvas1.width = clientWidth;canvas1.height = clientHeight;// 獲取自己的圓心坐標,為body中心const x = clientWidth / 2;const y = clientHeight / 2;// 畫自己的圓ctx.fillStyle = color;ctx.beginPath();ctx.arc(x, y, 15, 0, Math.PI * 2);ctx.fill();// 記錄自己的positionconst position = {top: y + barHeight + screenY,left: x + screenX,color: color,};// 獲取其它窗口position,并遍歷getOtherKeys().forEach(k => {const position2 = JSON.parse(localStorage.getItem(k)); // 獲取其中一個窗口的圓心positionconst w = position2.left - position.left; // 獲取相對自己圓心的橫向間距const h = position2.top - position.top; // 獲取相對自己圓心的縱向間距// 在自己的canvas上畫出該圓ctx.fillStyle = position2.color;ctx.beginPath();ctx.arc(x + w, y + h, 15, 0, Math.PI * 2);ctx.fill();// 畫連接線ctx.strokeStyle = "black";ctx.beginPath();ctx.moveTo(x, y);ctx.lineTo(x + w, y + h);ctx.stroke();})// 更新自己窗口的positionlocalStorage.setItem(key, JSON.stringify(position));// 記錄logalert2.textContent = JSON.stringify(localStorage, '', 2);window.requestAnimationFrame(draw);}window.requestAnimationFrame(draw);</script>
</body>
</html>