Implementing Multi‑Window 3D Synchronization with three.js

This article explains how to create a pure‑frontend “quantum entanglement” effect by synchronizing multiple browser windows using three.js, detailing the index.html setup, the main.js logic for scene and window management, and the WindowManager class that tracks window shapes via localStorage.

php Courses
php Courses
php Courses
Implementing Multi‑Window 3D Synchronization with three.js

The author demonstrates a pure‑frontend "quantum entanglement" visual effect where two browser windows display perfectly synchronized 3D scenes. The synchronization is achieved by sharing window geometry through localStorage and updating a three.js scene in each window.

index.html provides the basic HTML skeleton that loads three.js and the module script main.js:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>3d example using three.js and multiple windows</title>
    <script type="text/javascript" src="./three.r124.min.js"></script>
    <style type="text/css">
      * { margin:0; padding:0; }
    </style>
  </head>
  <body>
    <script type="module" src="./main.js"></script>
  </body>
</html>

The page loads three.js, defines a minimal CSS reset, and then executes main.js as an ES module.

main.js contains the core application logic. It imports a custom WindowManager class, creates a three.js orthographic camera, scene, renderer, and a world object that holds the cubes. The script sets up several functions: init() – initializes the scene after a short timeout, calls setupScene(), setupWindowManager(), resize(), and starts the render loop. setupScene() – creates the camera, scene background, renderer, and attaches the renderer DOM element to the document. setupWindowManager() – instantiates WindowManager, registers callbacks for window‑shape changes and window list updates, and adds the current window to the shared storage. updateNumberOfCubes() – reads the list of windows from the manager, removes any existing cubes, and creates a new cube for each window, positioning it at the window’s centre. render() – drives the animation, interpolates scene offsets, updates each cube’s position and rotation, and renders the scene each frame. resize() – adjusts the orthographic camera and renderer size when the browser window changes.

import WindowManager from './WindowManager.js';
const THREE = t;
let camera, scene, renderer, world;
let near, far;
let pixR = window.devicePixelRatio ? window.devicePixelRatio : 1;
let cubes = [];
let sceneOffsetTarget = { x: 0, y: 0 };
let sceneOffset = { x: 0, y: 0 };
// ... (rest of the functions as shown in the source) ...
function render() {
  let t = getTime();
  windowManager.update();
  // ... update cube positions and render ...
  requestAnimationFrame(render);
}

WindowManager.js implements a lightweight manager that shares window metadata across tabs using localStorage. It stores an array of window objects, each containing an id, shape (screen coordinates and size), and optional metaData. Key methods include: init(metaData) – registers the current window, assigns a unique ID, records its shape, and writes the data to localStorage. getWinShape() – returns the current window’s screenLeft, screenTop, innerWidth, and innerHeight. update() – detects changes in the window’s shape, updates the stored record, and triggers the registered shape‑change callback. setWinShapeChangeCallback(callback) and setWinChangeCallback(callback) – allow the application to react when a window moves/resizes or when the list of windows changes.

Utility getters such as getWindows(), getThisWindowData(), and getThisWindowID().

class WindowManager {
  #windows;
  #count;
  #id;
  #winData;
  #winShapeChangeCallback;
  #winChangeCallback;
  constructor() {
    let that = this;
    addEventListener("storage", (event) => {
      if (event.key == "windows") {
        let newWindows = JSON.parse(event.newValue);
        let winChange = that.#didWindowsChange(that.#windows, newWindows);
        that.#windows = newWindows;
        if (winChange && that.#winChangeCallback) that.#winChangeCallback();
      }
    });
    window.addEventListener('beforeunload', function(e) {
      let index = that.getWindowIndexFromId(that.#id);
      that.#windows.splice(index, 1);
      that.updateWindowsLocalStorage();
    });
  }
  // ... other methods as in the source ...
}
export default WindowManager;

By listening to the storage event, every tab receives updates when another tab adds, removes, or moves a window. The manager therefore keeps a consistent view of all open windows, which main.js uses to create a matching number of cubes and to align each cube with its corresponding window’s centre.

Overall, the article provides a complete, runnable example that shows how front‑end developers can achieve cross‑window visual synchronization without any back‑end services, leveraging only the browser’s native localStorage and three.js rendering capabilities.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScriptThree.jsWebGLmulti-windowwindow synchronization
php Courses
Written by

php Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

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.