var main = document.getElementById("main"); let orientation = 'landscape' // 'landscape' or 'portrait' /****************************************************** HTML generating *******************************************************/ // TODO /****************************************************** Background handling *******************************************************/ bg = document.getElementById("bg"); bgOld = bg; strokeArray = []; let websocketBackground = new WebSocket("ws://" + location.host + "/websocketBackground"); websocketBackground.onmessage = function(event) { if (typeof(event.data) == 'string') { bgInfo = JSON.parse(event.data); } else { //(event.data instanceof Binary) console.log(bgInfo); var imgblob = new Blob([event.data],{type:'image/png'}); var imgfile = URL.createObjectURL(imgblob); // prepare smooth transition bgOld = bg; bg = document.createElement('img'); bg.width = bgInfo.width; bg.height = bgInfo.heigth; bg.style = "position: absolute; transition: 250ms ease-in-out; opacity: 0"; bg.style.opacity = 0; bg.style.top = bgInfo.y_min + "px"; bg.style.left = bgInfo.x_min + "px"; bg_imgs.appendChild(bg); bg.src = imgfile; // on bg load, trigger transition an canvas redraw bg.onload = () => setTimeout(()=> bg.style.opacity = 1, 1); bg.ontransitionend = function() { strokeArray = strokeArray.filter(t => t[0] > bgInfo.ts); console.log('redrawing', strokeArray.length, 'strokes') ctx.clearRect(0, 0, canvas.width, canvas.height); for (let s of strokeArray) { draw(s[1]); }; if (bgInfo.is_diff == false) { while (bg.previousSibling != null) { bg.previousSibling.remove(); } } }; }; }; /****************************************************** Canvas and Hover-Overlay drawing *******************************************************/ var canvasOverlay = document.getElementById("canvas-overlay"); var ctxOverlay = canvasOverlay.getContext("2d"); var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var MAX_PRESSURE = 4095 // width, height in landscape as that is both native framebuffer and input format for (let cv of [canvas, canvasOverlay]) { cv.width = 1872; cv.height = 1404; }; ctx.lineCap = 'round'; function draw(stroke) { [lastX, lastY, x, y, pressure, tool] = stroke ctx.lineWidth = 1+(pressure/MAX_PRESSURE)*4; ctx.beginPath(); ctx.moveTo(lastX, lastY); ctx.lineTo(x, y); if (tool) { // pen: just draw ctx.stroke(); } else { // rubber: erase ctx.lineWidth = 60; ctx.save(); ctx.strokeStyle = 'linen'; ctx.globalAlpha = 0.4; ctx.stroke(); ctx.restore(); }; } function overlay(x, y) { // Clear when hovering, but keep drawing for the duration of a stroke to highlight it. if (!penState) { ctxOverlay.clearRect(0,0,canvasOverlay.width,canvasOverlay.height); } ctxOverlay.fillStyle = "rgb(200, 200, 255)"; ctxOverlay.beginPath(); ctxOverlay.arc(x, y, 10, 0, 2 * Math.PI); ctxOverlay.fill(); } let penState = false; let lastX = null; let lastY = null; let websocketInput = new WebSocket("ws://" + location.host + "/websocketInput"); websocketInput.onmessage = function(event) { // see websocket in server.rs TODO for data generation. let inputList = JSON.parse(event.data); for ({ts, x, y, pressure, tool} of inputList) { //for (cei of inputList) { overlay(x, y); // hover overlay is there as long is there is input if (pressure == 0) { // reset state penState = false; lastX = null; lastY = null; } else { if (penState) { stroke = [lastX, lastY, x, y, pressure, tool]; draw(stroke); strokeArray.push([ts, stroke]); } lastX = x; lastY = y; penState = true ; }; }; } document.addEventListener('keydown', logKey); function logKey(e) { if (e.keyCode == 13) { // enter for rotate if (orientation == 'landscape') { main.style.transform = 'rotate(270deg)'; main.style.transformOrigin = '1278px 600px'; orientation = 'portrait'; } else { main.style.transform = 'rotate(0deg)'; orientation = 'landscape'; } } }