Skip to content
Snippets Groups Projects
app.js 3.77 KiB
Newer Older
  • Learn to ignore specific revisions
  • // Room connection and synchronisation.
    // Translate local canvas input events to draw messages and send to the room.
    // Get back room updates and invoke the local canvas renderer.
    
    import * as canvas from "./canvas.js"
    
    import * as HTML from "./elements.js"
    
    import { connect } from "./room.js"
    
    
    const TEST_ROOM = "imperial"
    
    
    let room = null
    
    const onRoomConnect = (room_) => {
      room = room_
    
      HTML.connectedRoomID.textContent = room.name
      HTML.connectedRoomInfoContainer.style.display = "block"
    
      HTML.userIDElem.value = room.ownID || ""
    
      room.addEventListener("allocateOwnID", ({ detail: id }) => {
    
        HTML.userIDElem.value = id
    
      })
    
      room.addEventListener("userJoin", ({ detail: id }) => {
    
        if (HTML.connectedPeers.children.length == 0) {
    
        const peerElem = document.createElement("li")
        peerElem.innerHTML = id
    
        HTML.connectedPeers.appendChild(peerElem)
    
      })
    
      room.addEventListener("userLeave", ({ detail: id }) => {
    
        for (const peerElem of HTML.connectedPeers.children) {
    
          if (peerElem.innerHTML == id) {
    
            HTML.connectedPeers.removeChild(peerElem)
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
          }
    
        if (HTML.connectedPeers.children.length == 0) {
    
          HTML.connectedPeers.innerHTML = "No peers are connected"
        }
    
      })
    
      room.addEventListener("addOrUpdatePath", ({ detail: { id, points } }) => {
    
        canvas.renderPath(id, points)
    
    const tryRoomConnect = async (roomID) => {
      return await connect(roomID)
        .then(onRoomConnect)
        .catch((err) => alert(`Error connecting to a room:\n${err}`))
    }
    
    const ERASER_RADIUS = 10
    
    const tools = {
      PEN: Symbol("pen"),
      ERASER: Symbol("eraser"),
    }
    let currentTool = tools.PEN
    const pathIDsByPointerID = new Map()
    
    HTML.penButton.addEventListener("click", () => {
    
    Nayeem Rahman's avatar
    Nayeem Rahman committed
      currentTool = tools.PEN
      HTML.penButton.classList.add("selected")
      HTML.eraserButton.classList.remove("selected")
    
    HTML.eraserButton.addEventListener("click", () => {
      currentTool = tools.ERASER
      HTML.penButton.classList.remove("selected")
      HTML.eraserButton.classList.add("selected")
    })
    
    HTML.peerButton.addEventListener("click", () => {
      const peerID = HTML.peerIDElem.value
      if (room == null || peerID == "") {
        return
    
      room.inviteUser(peerID)
      HTML.peerIDElem.value = ""
    })
    
    HTML.roomConnectButton.addEventListener("click", () => {
      const selectedRoomID = HTML.roomIDElem.value
      if (!selectedRoomID || selectedRoomID == room.name) {
        return
    
      if (room != null) {
        room.disconnect()
        room = null
    
      canvas.clear()
      HTML.connectedPeers.innerHTML = "No peers are connected"
    
      tryRoomConnect(selectedRoomID)
    })
    
    const getDistance = (a, b) => {
      return Math.sqrt(
        (a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]),
      )
    }
    
    const erasePoint = ([x, y]) => {
      if (room == null) {
        return
    
      room.getPaths().forEach((points, pathID) => {
        points.forEach((point, i) => {
          if (getDistance([x, y], point) <= ERASER_RADIUS) {
            room.erasePoint(pathID, i)
          }
        })
      })
    }
    
    canvas.input.addEventListener("strokestart", ({ detail: e }) => {
      if (room == null) {
        return
      }
    
      const mousePos = [e.offsetX, e.offsetY]
    
      if (currentTool == tools.PEN) {
    
    Nayeem Rahman's avatar
    Nayeem Rahman committed
        pathIDsByPointerID.set(e.pointerId, room.addPath([...mousePos, e.pressure]))
    
      } else if (currentTool == tools.ERASER) {
        erasePoint(mousePos)
    
    canvas.input.addEventListener("strokeend", ({ detail: e }) => {
      pathIDsByPointerID.delete(e.pointerId)
    })
    
    canvas.input.addEventListener("strokemove", ({ detail: e }) => {
      if (room == null) {
        return
      }
    
      const mousePos = [e.offsetX, e.offsetY]
    
      if (currentTool == tools.PEN) {
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
        room.extendPath(pathIDsByPointerID.get(e.pointerId), [
    
    Giovanni Caruso's avatar
    Giovanni Caruso committed
        ])
    
      } else if (currentTool == tools.ERASER) {
        erasePoint(mousePos)
      }
    
    tryRoomConnect(TEST_ROOM)