Httprelay.io mcast example (shared painting canvas)

by Jonas Jasas

HTML

<header>
  <h1>Httprelay.io mcast example (shared painting canvas)</h1>
  <p>
    <a href="https://jsfiddle.net/jasajona/ky0cLgf9" target="_blank">Open this example</a> on other computer or in new browser window.
    This drawing canvas is shared among other users that are on the same data channel.
    Drawing data is sent as AJAX POST requests.
    Other users data is red as AJAX GET requests in infinite loop.
    You can set your private data channel by entering your channel name.
    This example is not optimized, it produces insane amount of requests.
  </p>

  <p>
    <em>IMPORTANT!</em> demo.httprelay.io instance runs in extremely limited environment.
    In order to evaluate performance or use it in production please 
    <a href="https://gitlab.com/jonas.jasas/httprelay#installation" target="_blank">run your own instance</a>.
  </p>
  
  <p>
    Data channel: https://demo.httprelay.io/mcast/<input id="mcastId" value="httprelay_examples-paint">
    <button id="reset">Clear canvas</button>
    <button id="history">Load history</button>
  </p>
  <em>Paint below the line:</em>  
</header>
<canvas id="canvas"></canvas>

CSS

html {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-content: stretch;
}

body {
  display: flex;
  flex: 1 0 100%;
  flex-direction: column;
  align-items: stretch;
  margin: 0;
}

header {
  flex: 0 1 auto;
  margin: 1em;
}

#canvas {
  display: flex;
  flex: 1 1 100%;
  border-top: 1px solid grey;
}

JavaScript

let mcastUrl
let color

let elCanvas = $('#canvas')
let ctx = elCanvas[0].getContext("2d")
$(window).on('resize load', () => reset())
$('#mcastId').on('change', () => reset())
$('#reset').on('click', () => reset())
$('#history').on('click', () => reset(true))

let drawDot = (x, y, c) => {
		ctx.beginPath();
    ctx.fillStyle = c
    ctx.arc(x, y, 5, 0, 360)
		ctx.fill()
}

elCanvas.on('mousemove mousedown', e => {
    if(e.buttons){
      let x = e.pageX - elCanvas.offset().left;
      let y = e.pageY - elCanvas.offset().top;
      drawDot(x, y, color)
	    $.ajax({url: mcastUrl, type: 'POST', data: x+'|'+y+'|'+color, contentType: 'text/plain'});	// Sending painted dot data
    }
});

$.ajaxSetup({xhrFields: {withCredentials: true}});	// Important place, enables cookies! SeqId (order of requests) is passed via cookies
let getXhr
let receive = (fromOldest) => {	
  if (getXhr) getXhr.abort()
  url = fromOldest ? mcastUrl+'?SeqId=0&nocache='+$.now() : mcastUrl
  getXhr = $.get(url).done((data) => {	// Reading data in infinite loop
    let d = data.split('|')
    drawDot(d[0], d[1], d[2]);
  }).always(() => receive());
}

let reset = (fromOldest) => {
  ctx.canvas.width  = ctx.canvas.clientWidth
  ctx.canvas.height = ctx.canvas.clientHeight
  mcastUrl = 'https://demo.httprelay.io/mcast/' + $('#mcastId').val()
  color = '#'+Math.floor(Math.random()*16777215).toString(16)
  receive(fromOldest);
}