Live cursors
Everyone on this page, and on the home page, shares one presence channel. Move over the canvas and your position goes straight to the other browsers.
Move your pointer here, drag a finger, or focus the canvas and use the arrow keys.
How it works
The channel name starts with presence-, so joining needs a signature from a server that holds
the app secret. This site's backend signs a name and a colour for each visitor; that data is what shows up
in the member list.
Positions are client messages (opcode 8): the server relays them to the other members without
calling your backend. They are sent as fractions of the canvas so pointers line up on any screen size, and
throttled to one every 50 ms. The server rejects client messages that arrive less than 20 ms apart.
const channel = pikoman.listenPresence("presence-cursors", authenticator);
// Fires on join and whenever someone arrives or leaves.
channel.members((members) => {
for (const [id, { name, color }] of members) drawPointer(id, name, color);
});
// Client messages carry the sender's id first.
channel.on("move", (id, { x, y }) => movePointer(id, x, y));
canvas.addEventListener("pointermove", throttle((e) => {
channel.send("move", toFraction(e));
}, 50));