Skip to content

Instantly share code, notes, and snippets.

@untillnesss
Forked from 000hen/index.html
Created May 22, 2026 06:21
Show Gist options
  • Select an option

  • Save untillnesss/b9df1c27455a0f229a18228b477881cc to your computer and use it in GitHub Desktop.

Select an option

Save untillnesss/b9df1c27455a0f229a18228b477881cc to your computer and use it in GitHub Desktop.
Experimential Cross Tab Communication
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cross Tab Communication</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: hidden;
}
</style>
</head>
<body>
<canvas id="default"></canvas>
<script src="/index.js"></script>
</body>
</html>
const TAB_ID = crypto.randomUUID();
const TAB_TIMEOUT = 100;
const channel = new BroadcastChannel('cross-tab-com');
const canvas = document.getElementById('default');
const ctx = canvas.getContext('2d');
const posMap = {};
const lastSeenMap = {};
channel.addEventListener('message', (event) => {
if (event.data.tabId === TAB_ID) return;
posMap[event.data.tabId] = { x: event.data.x, y: event.data.y };
lastSeenMap[event.data.tabId] = performance.now();
});
function getWindowMiddlePosition() {
const chromeHeight = window.outerHeight - window.innerHeight;
return {
x: window.screenX + window.innerWidth / 2,
y: window.screenY + chromeHeight + window.innerHeight / 2,
};
}
function globalToLocal(globalX, globalY) {
const chromeHeight = window.outerHeight - window.innerHeight;
return {
x: globalX - window.screenX,
y: globalY - window.screenY - chromeHeight,
};
}
function post() {
const { x, y } = getWindowMiddlePosition();
channel.postMessage({ tabId: TAB_ID, x, y });
}
function period() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawLines();
drawPoints();
requestAnimationFrame(period);
}
function drawLines() {
const currentGlobal = getWindowMiddlePosition();
const currentLocal = globalToLocal(
currentGlobal.x,
currentGlobal.y
);
const points = [{ x: currentLocal.x, y: currentLocal.y }];
for (const id in posMap) {
const remoteGlobal = posMap[id];
const remoteLocal = globalToLocal(remoteGlobal.x, remoteGlobal.y);
points.push({ x: remoteLocal.x, y: remoteLocal.y });
}
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
for (let i = 0; i < points.length; i++) {
for (let j = i + 1; j < points.length; j++) {
ctx.beginPath();
ctx.moveTo(points[i].x, points[i].y);
ctx.lineTo(points[j].x, points[j].y);
ctx.stroke();
}
}
}
function drawPoints() {
const currentGlobal = getWindowMiddlePosition();
const currentLocal = globalToLocal(
currentGlobal.x,
currentGlobal.y
);
ctx.beginPath();
ctx.arc(currentLocal.x, currentLocal.y, 10, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
for (const id in posMap) {
const remoteGlobal = posMap[id];
const remoteLocal = globalToLocal(
remoteGlobal.x,
remoteGlobal.y
);
ctx.beginPath();
ctx.arc(remoteLocal.x, remoteLocal.y, 10, 0, 2 * Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
}
}
function resizeCanvas() {
canvas.width = window.outerWidth;
canvas.height = window.outerHeight;
}
function cleanupDeadTabs() {
const now = performance.now();
for (const id in lastSeenMap) {
if (now - lastSeenMap[id] > TAB_TIMEOUT) {
delete lastSeenMap[id];
delete posMap[id];
}
}
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
period();
setInterval(post, 10);
setInterval(cleanupDeadTabs, 100);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment