The issue is that the live cursor's position on other users' screens is not accurately represented due to differences in screen resolutions, zoom levels, or the positioning of ReactFlow elements caused by individual user interactions. These disparities result in an improper alignment of the live cursor on remote displays, making it appear misplaced or misaligned. To achieve seamless collaboration, it is essential to ensure that the live cursor's position is precisely adjusted and synchronized across all users' screens, considering various factors such as resolution, zoom levels, and user interactions with ReactFlow elements.
I have successfully resolved this issue by adjusting the live cursor's position based on the zoom level and the ReactFlow's current position on other users' screens.
// Implement the live cursor component as follows:
import { FC, useEffect } from "react";
import { useReactFlow } from "reactflow"
import useLiveBlocksStore from "@/stores/useLiveBlocksStore";
interface LiveCursorProps {
cursorPos: { x: number, y: number };
}
const LiveCursor: FC<LiveCursorProps> = ({cursorPos }) => {
const reactFlowInstance = useReactFlow()
const {
updateMyPresence,
liveblocks: { others },
} = useLiveBlocksStore()
useEffect(() => {
const position = reactFlowInstance.project({ x: cursorPos.x, y: cursorPos.y });
//Liveblocks method to set the curren cursor positon
updateMyPresence({
cursor: { x: Math.round(position.x), y: Math.round(position.y) }
})
}, [cursorPos])
return (
<>
{
others.map((other) => {
if (other.presence.cursor == null) {
return null
}
// get current Reactflow screen viewPort
const otherViewPort = reactFlowInstance.getViewport();
//fixing the x, y position of cursor in other screen inside of react flow
let xPos = other.presence.cursor.x * otherViewPort.zoom + otherViewPort.x;
let yPos = other.presence.cursor.y * otherViewPort.zoom + otherViewPort.y;
return (
/* The cursor component takes the x and y coordinates of the cursor
and accurately displays it in the correct position on other users' screens. */
<Cursor key={other.id} x={xPos} y={yPos} />
)
})
}
</>
}
export default LiveCursor
Pass your component as a child component to the ReactFlow component, and ensure that the position of this component is set to absolute.
const [cursorPos, setCurosrPos] = useState({ x: 0, y: 0 })
const handleMouseMove = (event: React.MouseEvent) => {
setCurosrPos({ x: event.clientX, y: event.clientY });
};
return <div style={{position:"absolute",left:0, top:0, overflowY:"auto", width:"100vw" height:"100vh"}} >
<ReactFlow
fitView
nodes={nodes}
edges={edges}
onMouseMove={handleMouseMove}
>
<div style={{zIndex:10,position:"absolute"}} >
<LiveCursors cursorPos={cursorPos} />
</div>
</ReactFlow>
</div>