Skip to content

Commit

Permalink
cursors 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Pangoraw committed Nov 24, 2023
1 parent 2570e1a commit a7afa70
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
50 changes: 45 additions & 5 deletions frontend/components/MultiplayerPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,43 @@ import { PlutoActionsContext } from "../common/PlutoContext.js"
// .... update notebook should be pretty fast.
const CURSOR_THROTTLE_RATE = 100

const mouse_data_to_point = ({relative_to_cell, relative_x, relative_y}) => {
const cell_elt = document.getElementById(relative_to_cell)

if (cell_elt === null) {
// Cell might not be synced
return [relative_x, relative_y]
}

return [
relative_x + cell_elt.offsetLeft,
relative_y + cell_elt.offsetTop,
]
}

const update_mouse_data = (mouseX, mouseY) => {
const cell_nodes = Array.from(document.querySelectorAll("pluto-notebook > pluto-cell"))

let best_index = null
let best_dist = Infinity
let relative_x = mouseX
let relative_y = mouseY

const mousePt = [mouseX, mouseY]

for (let cell_elt of cell_nodes) {
const dist_with_cell = dist2(mousePt, [cell_elt.offsetLeft, cell_elt.offsetTop])
if (dist_with_cell < best_dist) {
best_dist = dist_with_cell
best_index = cell_elt.id
relative_x = mouseX - cell_elt.offsetLeft
relative_y = mouseY - cell_elt.offsetTop
}
}

return { relative_to_cell: best_index, relative_x, relative_y }
}

// https://github.com/steveruizok/perfect-cursors/tree/main?tab=readme-ov-file#usage-in-react
const usePerfectCursor = (cb, point) => {
const [pc] = useState(() => new PerfectCursor(cb))
Expand All @@ -23,6 +60,9 @@ const usePerfectCursor = (cb, point) => {
return onPointChange
}

const hexToRGBA = (hex, alpha) => `rgba(${parseInt(hex.slice(1,3),16)},${parseInt(hex.slice(3,5),16)},${parseInt(hex.slice(5,8),16)},${alpha})`
const dist2 = ([x1,y1], [x2,y2]) => (x1 - x2) ^ 2 + (y1 - y2) ^ 2

const Cursor = ({ mouse: point, color }) => {
if (!point) return
const r = useRef(null)
Expand All @@ -36,6 +76,8 @@ const Cursor = ({ mouse: point, color }) => {
const onPointMove = usePerfectCursor(animate)
useLayoutEffect(() => onPointMove(point), [point, onPointMove])

color = color ?? "#eeeeee"

return html`
<div
ref=${r}
Expand All @@ -46,6 +88,7 @@ const Cursor = ({ mouse: point, color }) => {
width: 20,
height: 20,
borderRadius: 10,
border: "solid 8px " + hexToRGBA(color , 0.5 ),
backgroundColor: color,
}}
></div>
Expand All @@ -66,10 +109,7 @@ export const MultiplayerPanel = ({ users, client_id }) => {
usePassiveDocumentEventListener("mousemove", _.throttle((event) => {
update_notebook(notebook => {
if (!(client_id in notebook.users)) return
notebook.users[client_id].mouse = [
event.clientX,
event.clientY,
]
notebook.users[client_id].mouse = update_mouse_data(event.pageX, event.pageY)
})
}, CURSOR_THROTTLE_RATE), [client_id])

Expand All @@ -84,7 +124,7 @@ export const MultiplayerPanel = ({ users, client_id }) => {
${Object.entries(users).map(
([clientID, { name, mouse, color, focused_cell }]) =>
html`<li key=${clientID} style=${`color: ${color};`}>${name} - ${focused_cell}
${client_id == clientID ? null : html`<${Cursor} mouse=${mouse} color=${color} />`}
${client_id == clientID || !mouse ? null : html`<${Cursor} mouse=${mouse_data_to_point(mouse)} color=${color} />`}
</li>`
)}
</ul>
Expand Down
2 changes: 2 additions & 0 deletions frontend/imports/PerfectCursors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { PerfectCursor } from "https://cdn.jsdelivr.net/npm/[email protected]/dist/esm/index.js"
export { PerfectCursor }

0 comments on commit a7afa70

Please sign in to comment.