Simultaneous Cursors
This demo shows the real-time collaborative version of simple drawing, cursor animation with Yorkie and React.
App.jsx
1import { useEffect, useState } from 'react';2import yorkie from 'yorkie-js-sdk';3import Cursor from './components/Cursor';4import CursorSelections from './components/CursorSelections';5import './App.css';67const client = new yorkie.Client(import.meta.env.VITE_YORKIE_API_ADDR, {8 apiKey: import.meta.env.VITE_YORKIE_API_KEY,9});1011const doc = new yorkie.Document('simultaneous-cursors');1213const App = () => {14 const [clients, setClients] = useState([]);1516 const handleCursorShapeSelect = (cursorShape) => {17 doc.update((root, presence) => {18 presence.set({19 cursorShape,20 });21 });22 };2324 useEffect(() => {25 const setup = async () => {26 await client.activate();2728 doc.subscribe('presence', (event) => {29 setClients(doc.getPresences());30 });3132 await client.attach(doc, {33 initialPresence: {34 cursorShape: 'cursor',35 cursor: {36 xPos: 0,37 yPos: 0,38 },39 pointerDown: false,40 },41 });4243 window.addEventListener('beforeunload', () => {44 client.deactivate();45 });46 };4748 setup();4950 const handlePointerUp = () => {51 doc.update((root, presence) => {52 presence.set({53 pointerDown: false,54 });55 });56 };57 const handlePointerDown = () => {58 doc.update((root, presence) => {59 presence.set({60 pointerDown: true,61 });62 });63 };64 const handleMouseMove = (event) => {65 doc.update((root, presence) => {66 presence.set({67 cursor: {68 xPos: event.clientX,69 yPos: event.clientY,70 },71 });72 });73 };7475 window.addEventListener('mousedown', handlePointerDown);76 window.addEventListener('mouseup', handlePointerUp);77 window.addEventListener('mousemove', handleMouseMove);7879 return () => {80 window.removeEventListener('mousedown', handlePointerDown);81 window.removeEventListener('mouseup', handlePointerUp);82 window.removeEventListener('mousemove', handleMouseMove);83 };84 }, []);8586 return (87 <div className="general-container">88 {clients.map(89 ({ clientID, presence: { cursorShape, cursor, pointerDown } }) => {90 return (91 <Cursor92 selectedCursorShape={cursorShape}93 x={cursor.xPos}94 y={cursor.yPos}95 pointerDown={pointerDown}96 key={clientID}97 />98 );99 },100 )}101102 <CursorSelections103 handleCursorShapeSelect={handleCursorShapeSelect}104 clientsLength={clients.length}105 />106 </div>107 );108};109110export default App;
- User 1
- User 2
- User 1
- User 2
Event Log