Frontend Development 10 min read

Cross‑Window Real‑Time Rendering with Canvas, window.screenX/Y and localStorage

This article demonstrates how to create a multi‑window, real‑time interactive animation using pure JavaScript by drawing circles on a canvas, sharing each window's screen coordinates and colors through localStorage, and connecting them with lines across browsers.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Cross‑Window Real‑Time Rendering with Canvas, window.screenX/Y and localStorage

The author describes a technique for building a cross‑window, real‑time interactive animation entirely with JavaScript, without third‑party libraries. Each browser window draws a circle at its center on a canvas , stores its screen coordinates ( window.screenX , window.screenY ) and a color in localStorage , and reads other windows' data to render connecting lines.

Key APIs used :

window.requestAnimationFrame – for the animation loop.

const { screenX, screenY } = window – to obtain the window's position relative to the screen.

const barHeight = window.outerHeight - window.innerHeight – to calculate the browser UI height.

canvas – the drawing surface.

localStorage – shared storage for all pages under the same origin.

Core drawing logic (simplified) :

const alert1 = document.getElementById('alert1');
const alert2 = document.getElementById('alert2');
const canvas1 = document.getElementById('canvas1');
const ctx = canvas1.getContext('2d');

function draw() {
  const { clientWidth, clientHeight } = document.body;
  const { screenX, screenY } = window;
  const barHeight = window.outerHeight - window.innerHeight;

  // log current window info
  alert1.textContent = JSON.stringify({ clientWidth, clientHeight, screenX, screenY, barHeight }, null, 2);

  canvas1.width = clientWidth;
  canvas1.height = clientHeight;

  const x = clientWidth / 2;
  const y = clientHeight / 2;

  // draw own circle
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.arc(x, y, 15, 0, Math.PI * 2);
  ctx.fill();

  const position = { top: y + barHeight + screenY, left: x + screenX, color };

  // draw other windows' circles and connecting lines
  getOtherKeys().forEach(k => {
    const position2 = JSON.parse(localStorage.getItem(k));
    const w = position2.left - position.left;
    const h = position2.top - position.top;

    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();
  });

  // update own position in storage
  localStorage.setItem(key, JSON.stringify(position));
  alert2.textContent = JSON.stringify(localStorage, null, 2);

  window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);

Utility functions manage storage keys, assign a unique key to each window, and clean up on window.onunload :

function getOtherKeys() {
  const keys = [];
  for (let i = 0; i < localStorage.length; i++) {
    const k = Number(localStorage.key(i));
    if (!isNaN(k)) keys.push(k);
  }
  return keys.sort((a, b) => a - b);
}

window.onunload = function () {
  localStorage.removeItem(key);
};

The article concludes with the full source code, a summary of current limitations (e.g., missing connection lines when windows overlap), and links to the GitHub repository and live demo for further exploration.

animationJavaScriptCanvaslocalStoragecross-windowwindow API
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.