Recursive Photos

This was the group project that Elizabeth and I worked on for the HTML5 Audio/Video assignment. We had originally wanted to capture live video from each user’s webcam and draw that video onto a canvas at the location of the user’s cursor. Essentially creating a space of talking heads where each user could control their own position, with further goal of allowing the user to draw on their canvas. However, we ran into a lot of obstacles trying this method, and eventually came to the realization that this wasn’t the best way to go about this. So we scaled our efforts back to simply capturing an image and printing it to a shared canvas. We got that running, but not to the desired effect. Instead of simply capturing an image from the webcam and printing that to canvas, it would capture the entire canvas already drawn in addition to an image from the webcam. This created a recursive effect, that got exponentially more chaotic as more users took pictures.

We realized that we would need an additional canvas for each user that would not be drawn to the screen, but would simply hold the webcam information to sucessfully draw just the webcam image to a DATA URI, instead of drawing the canvas that is already on the screen.

Here are the index.html and the server file:

<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
    <script type="text/javascript">

    let mouseX;
    let mouseY;
    // let windowWidth = window.innerWidth;
    // let windowHeight = window.innerHeight;

    window.addEventListener('load', function() {
      // The video element on the page to display the webcam
      var video = document.getElementById('thevideo');
      //var video = document.createElement('thevideo');
      // video.setAttribute('autoplay',true);


      // Constraints - what do we want?
      let constraints = { audio: false, video: true };

      // Prompt the user for permission, get the stream
      navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
      	/* Use the stream */

      	// Attach to our video object
      	video.srcObject = stream;

      	// Wait for the stream to load enough to play
      	video.onloadedmetadata = function(e) {
      		video.play();
          // draw();

      	};
      })
      .catch(function(err) {
      	/* Handle the error */
      	alert(err);
      });

      // Canvas element on the page
      var thecanvas = document.getElementById('thecanvas');
            thecanvas.width = window.innerWidth;
            thecanvas.height = window.innerHeight;
      console.log(thecanvas);

      console.log(video);

      // var draw = function() {
      //   // console.log("Drawing");
      //   thecontext.clearRect(0, 0, thecanvas.width, thecanvas.height);
      //   // console.log("It should be drawing!");
      // 	// Draw the video onto the canvas
      //
      //   dataUrl = thecanvas.toDataURL();
      //   // var dataUrl = video;
      //   // console.log(dataUrl);
      //
      //   socket.emit('dataurl', dataUrl, socket.id);
      //
      // 	// document.getElementById('imagefile').src = dataUrl;
      //   document.getElementById('thecanvas').src = dataUrl;
      //
      //
      //
      // 	// Draw again in 30 milliseconds
      // 	setTimeout(draw, 30);
      // };

        thebody.addEventListener('mousemove', function(e) {
        // console.log(e.x, e.y);
        socket.emit('coordinates', {x: e.x, y: e.y});
        // mouseX = e.x;
        // mouseY = e.y;
      });

      thebody.addEventListener('mousedown', function() {
        console.log("click");

        // var dataUrl = video;
        var video = document.getElementById('thevideo');
        var thecanvas = document.getElementById('thecanvas');
        var thecontext = thecanvas.getContext('2d');
        thecontext.drawImage(video,mouseX,mouseY,320,240);
        var dataUrl = thecanvas.toDataURL();
        socket.emit('dataurl', dataUrl);

      	// document.getElementById('imagefile').src = dataUrl;
        // document.getElementById('thecanvas').src = dataUrl;
        });

    });


    var socket = io.connect();

    socket.on('connect', function() {
      console.log("Connected");
      // socket.emit('createCanvas')
    });

    // socket.on('createCanvas', function(data) {
    //   console.log("Canvas created: " + socket.id);
    //   console.log(data + " Other person");
    //   var userCanvas = document.createElement("canvas");
    //   userCanvas.id = data;
    //   userCanvas.width = window.innerWidth;
    //   userCanvas.height = window.innerHeight;
    //   userCanvas.style.left = "0px";
    //   userCanvas.style.right = "0px";
    //   document.body.appendChild(userCanvas);
    // });

    socket.on('coordinates', function(data) {
      mouseX = data.x;
      mouseY = data.y
    });

    socket.on('dataurl', function(data) {
      console.log("Data URL Request");
      // console.log(id);

      // var video = document.getElementById('thevideo');
      // var thecontext = thecanvas.getContext('2d');
      // thecontext.drawImage(video,mouseX,mouseY,320,240);

      // console.log(data);
      // thecontext.drawImage(img,0,0,320,240);
      // img.src = data;

      var thecanvas = document.getElementById('thecanvas');

      var thecontext = thecanvas.getContext('2d');
      var img = new Image();
      console.log(img);
      img.onload = function() {
      thecontext.drawImage(img,mouseX,mouseY,320,240);
      console.log("We made it this far.")
      };
      img.src = data;

      //
      // var theimage = document.createElement("img");
      // theimage.src = data;
      // document.body.appendChild(theimage);
    });



  </script>
</head>
<body id="thebody">
  <video id="thevideo" height="0" width="0"></video>
  <canvas id="thecanvas"></canvas>
  <img id="theimage"></img>
  <!-- <div id="thediv">x</div> -->
</body>
</html>

//var http = require('http');
var https = require('https');

var fs = require('fs'); // Using the filesystem module

var options = {
  key: fs.readFileSync('my-key.pem'),
  cert: fs.readFileSync('my-cert.pem')
};

//var httpServer = http.createServer(requestHandler);

var httpServer = https.createServer(options, requestHandler);
httpServer.listen(8080);


var url = require('url');
// httpServer.listen(8080);
console.log('Server listening on port 8080');

function requestHandler(req, res) {

  var parsedUrl = url.parse(req.url);
  console.log("The Request is: " + parsedUrl.pathname);

  // Read in the file they requested
  fs.readFile(__dirname + parsedUrl.pathname,
    // Callback function, called when reading is complete
    function(err, data) {
      // if there is an error
      if (err) {
        res.writeHead(500);
        return res.end('Error loading ' + parsedUrl.pathname);
      }
      // Otherwise, send the data, the contents of the file
      res.writeHead(200);
      res.end(data);
    }
  );
}

// var numUsers = 0;
// var maxNumUsers = 2;

// WebSocket Portion
// WebSockets work with the HTTP server
var io = require('socket.io').listen(httpServer);

// Register a callback function to run when we have an individual connection
// This is run for each individual user that connects
io.sockets.on('connection',
  // We are given a websocket object in our function
  function(socket) {

    // if (numUsers < maxNumUsers) {
    // numUsers++;
    console.log("We have a new client: " + socket.id);

    socket.on('coordinates', function(data) {
      io.sockets.emit('coordinates', data);
    });

    socket.on('dataurl', function(data) {
      io.sockets.emit('dataurl', data);
    });

    socket.on('connect', function(data) {
      console.log("New connection" + socket.id);
      // io.sockets.emit('createCanvas', socket.id);
      // console.log(data);
    });

    // socket.on('createCanvas', function(data) {
    //   console.log("Canvas Created: " + socket.id);
    //   io.sockets.emit('createCanvas', socket.id);
    //   // console.log(data);
    // });

    // When this user "send" from clientside javascript, we get a "message"
    // client side: socket.send("the message");  or socket.emit('message', "the message");
    socket.on('message',
      // Run this function when a message is sent
      function(data) {
        console.log("message: " + data);

        // Call "broadcast" to send it to all clients (except sender), this is equal to
        // socket.broadcast.emit('message', data);
        //socket.broadcast.send(data);

        // To all clients, on io.sockets instead
        io.sockets.emit('message', data);
      }
    );

    socket.on('draw',
      // Run this function when a message is sent
      function(data) {
        // console.log(data);

        // Call "broadcast" to send it to all clients (except sender), this is equal to
        // socket.broadcast.emit('message', data);
        //socket.broadcast.send(data);

        // To all clients, on io.sockets instead
        io.sockets.emit('draw', data);
      }
    );

    socket.on('blink',
      // Run this function when a message is sent
      function(data) {
        console.log(data);

        // Call "broadcast" to send it to all clients (except sender), this is equal to
        // socket.broadcast.emit('message', data);
        //socket.broadcast.send(data);

        // To all clients, on io.sockets instead
        io.sockets.emit('blink', data);
      }
    );

    // When this user emits, client side: socket.emit('otherevent',some data);
    socket.on('otherevent', function(data) {
      // Data comes in as whatever was sent, including objects
      console.log("Received: 'otherevent' " + data);
    });


    socket.on('disconnect', function() {
      console.log("Client has disconnected");
      // numUsers--;
    });
    // } else {
    //   socket.disconnect();
    //
    // }
  }
);
Written on October 9, 2018