Skip to content
Snippets Groups Projects
app.js 6.48 KiB
Newer Older
import { line, curveBasis } from "d3-shape"
Nayeem Rahman's avatar
Nayeem Rahman committed
import uuidv4 from "uuid/v4"
import yMemory from "y-memory"
import yMap from "y-map"
import yArray from "y-array"
import Y from "yjs"
Nayeem Rahman's avatar
Nayeem Rahman committed
import yWebrtc from "./y-webrtc/index.js"

yMemory(Y)
yMap(Y)
yArray(Y)
yWebrtc(Y)
  },
  connector: {
    name: "webrtc",
  const userIDElem = document.getElementById("user-id")
  const peerIDElem = document.getElementById("peer-id")
  const peerButton = document.getElementById("peer-connect")
  const connectedP = document.getElementById("connected-peers")
  const penButton = document.getElementById("pen")
  const eraserButton = document.getElementById("eraser")

  userIDElem.value = y.db.userId

  y.connector.onUserEvent(function(event) {
    switch (event.action) {
      case "userID":
        userIDElem.value = event.id
        break
      case "userJoined":
        var peerElem = document.createElement("li")
        peerElem.innerHTML = event.user
        connectedP.appendChild(peerElem)
        break
      case "userLeft":
        for (var peer of connectedP.children) {
          if (peer.innerHTML == event.user) {
            connectedP.removeChild(peer)
          }
        }
        break
    }
  })

  peerButton.onclick = function() {
    const peerID = peerIDElem.value

    if (peerID == "") {
      return
    }

    y.connector.connectToPeer(peerID)

    peerIDElem.value = ""
  // Used to check what kind of tool is selected
  var addingLine = true
  var removingLine = false

Giovanni Caruso's avatar
Giovanni Caruso committed
  const CHECKRADIUS = 10

  penButton.onclick = function() {
    // If pen tool selected
    if (!addingLine) {
      addingLine = true
      removingLine = false
    }
  }

  eraserButton.onclick = function() {
    // If eraser tool selected
    if (!removingLine) {
      removingLine = true
      addingLine = false
    }
  }

  const whiteboard = document.getElementById("whiteboard")

  var input = false
  var paths = new Map()
  var pathID

  function createOrUpdatePath(uid, points) {
    const lineFn = line()
      .x((d) => d[0])
      .y((d) => d[1])
      .curve(curveBasis)

    var path = paths.get(uid)

    if (path === undefined) {
      path = document.createElementNS("http://www.w3.org/2000/svg", "path")

      path.setAttribute("stroke", "blue")
      path.setAttribute("stroke-width", 3)
      path.setAttribute("fill", "none")
      path.setAttribute("pointer-events", "none")

      whiteboard.appendChild(path)

      paths.set(uid, path)
    }

    points = points.toArray().filter((point) => point !== undefined)

    if (points.length <= 0) {
      path.removeAttribute("d")

      return path
    }

Giovanni Caruso's avatar
Giovanni Caruso committed
    console.log(points)
    console.log(path)

  function removeOrUpdatePath(uid) {
    var path = paths.get(uid)

    if (path !== undefined) {
      paths.delete(path)
    }
  }

    if (addingLine) {
      pathID = uuidv4()
      const sharedPath = y.share.drawing.set(pathID, Y.Array)
Giovanni Caruso's avatar
Giovanni Caruso committed
      sharedPath.push([[mouse.x, mouse.y, true]])
    } else if (removingLine) {
      // Iterate over all the possible paths in the Map
      const mapPaths = y.share.drawing.keys()
      for (var mapPath of mapPaths) {
        var found = false
        // Get the array of coordinates
Giovanni Caruso's avatar
Giovanni Caruso committed
        var mouseYArray = y.share.drawing.get(mapPath)
        var mouseArray = mouseYArray.toArray()

        // Check the array for current position
        for (var i = 0; i < mouseArray.length; i++) {
Giovanni Caruso's avatar
Giovanni Caruso committed
          var point = mouseArray[i]
          if (checkRadius(point, mouse)) {
            // Delete point
            point[2] = false
Giovanni Caruso's avatar
Giovanni Caruso committed
            mouseYArray.insert(i, point)
            y.share.drawing.set(mapPath, mouseYArray)
Giovanni Caruso's avatar
Giovanni Caruso committed
  /* Helper function that checks whether a point is within the mouse radius */
  function checkRadius(mouseMap, mouse) {
    var mouseMapX = mouseMap[0]
    var mouseMapY = mouseMap[1]
    var mouseX = mouse.x
    var mouseY = mouse.y

    for (var i = 0; i < CHECKRADIUS; i++) {
      // Chech x-axis
      if (mouseX + i == mouseMapX) {
        return true
      } else if (mouseX - i == mouseMapX) {
        return true
      }

      // Check y-axis
      if (mouseY + i == mouseMapY) {
        return true
      } else if (mouseY - i == mouseMapY) {
        return true
      }
    }

    return false
  }

  }

  whiteboard.onmousemove = function(e) {
    const mouse = {
      x: e.offsetX,
      y: e.offsetY,
    }

    if (input) {
      if (addingLine) {
        const sharedPath = y.share.drawing.get(pathID)
Giovanni Caruso's avatar
Giovanni Caruso committed
        sharedPath.push([[mouse.x, mouse.y, true]])
      } else if (removingLine) {
        // Iterate over all the possible paths in the Map
        const mapPaths = y.share.drawing.keys()
        for (var mapPath of mapPaths) {
          var found = false
          // Get the array of coordinates
Giovanni Caruso's avatar
Giovanni Caruso committed
          var mouseYArray = y.share.drawing.get(mapPath)
          var mouseArray = mouseYArray.toArray()

          // Check the array for current position
          for (var i = 0; i < mouseArray.length; i++) {
Giovanni Caruso's avatar
Giovanni Caruso committed
            var point = mouseArray[i]
            if (checkRadius(point, mouse)) {
              // Delete point
              point[2] = false
Giovanni Caruso's avatar
Giovanni Caruso committed
              mouseYArray.insert(i, point)
              y.share.drawing.set(mapPath, mouseYArray)
    }
  }

  y.share.drawing.observe(function(lineEvent) {
    const lineID = lineEvent.name

    switch (lineEvent.type) {
      case "add":
        createOrUpdatePath(lineID, lineEvent.value)

        lineEvent.value.observe(function(pointEvent) {
          switch (pointEvent.type) {
            case "insert":
              createOrUpdatePath(lineID, pointEvent.object)
              break
          }
        })

Giovanni Caruso's avatar
Giovanni Caruso committed
      case "update":
        removeOrUpdatePath(lineID)

Giovanni Caruso's avatar
Giovanni Caruso committed
        lineEvent.value.observe(function(pointEvent) {
          switch (pointEvent.type) {
            case "insert":
              removeOrUpdatePath(lineID)
              break
          }
        })