diff --git a/html/logic.js b/html/logic.js new file mode 100644 index 0000000..f078b4d --- /dev/null +++ b/html/logic.js @@ -0,0 +1,267 @@ +const socket = new WebSocket("ws://localhost:7865"); +var canvas = document.getElementById("board"); +var colorInput = document.getElementById("color"); +var canvasHidden = document.getElementById("hidden"); +var ctx = canvas.getContext("2d"); +var ctx2 = canvasHidden.getContext("2d"); +var currentColor = "#000000" +canvas.width = 1920; +canvas.height = 1080; +canvasHidden.width = 1920; +canvasHidden.height = 1080; +var imgData = ctx2.createImageData(canvasHidden.width, canvasHidden.height) + +function drawPixel(x, y, color) { + let pixelNumber; + if (y > 0) + pixelNumber = (y) * canvas.width + x + if (y == 0) + pixelNumber = x + if (color == undefined) rgbColor = hexToRgb(currentColor); + for (let l = 0; l < 4; l ++) + for (let l = 0; l < 5; l ++){ + imgData.data[pixelNumber + 0] = color == undefined? rgbColor.r : color.r; + imgData.data[pixelNumber + 1] = color == undefined? rgbColor.g : color.g; + imgData.data[pixelNumber + 2] = color == undefined? rgbColor.b : color.b; + imgData.data[pixelNumber + 3] = 255; + } + + redraw(); + } + +function redraw() { + ctx.save(); + ctx.setTransform(1,0,0,1,0,0); + ctx.clearRect(0,0,canvas.width,canvas.height); + ctx.restore(); + + ctx2.putImageData(imgData, 0, 0); + ctx.drawImage(canvasHidden, 0, 0) + ctx.imageSmoothingEnabled = false + } + +socket.addEventListener("open", (event) => { + socket.send("{\"code\":0}"); +}); + +socket.addEventListener("message", (event) => { + // console.log("Message from server ", JSON.stringify(event.data.toString())); + event.data.text().then(function(packet){ + packet = JSON.parse(packet) + let code = packet.code + let content = packet.content + switch (code){ + case 0: + //Ineffective way to do that, fix that later ;) + let converted = Uint8ClampedArray.from(content) + + for (let i = 0; i < converted.length; i ++) + imgData.data[i] = converted[i] + redraw(); + break; + case 1: + contentJson = JSON.parse(content); + let color = { + r: contentJson.r, + g: contentJson.g, + b: contentJson.b + } + + drawPixel(contentJson.x * 4, contentJson.y * 4, color) + redraw(); + break; + } + }); +}); + +// All the code that is making zooms and moving around cavnas is made with big help of http://phrogz.net/tmp/canvas_zoom_to_cursor.html. Thanks alot! +window.onload = function() { + var ctx = canvas.getContext("2d"); + trackTransforms(ctx); + + var lastX=canvas.width/2, lastY=canvas.height/2; + var dragStart,dragged; + canvas.addEventListener('mousedown',function(evt){ + if (evt.button == 1 || 1 == evt.button&2){ + document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none'; + lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft); + lastY = evt.offsetY || (evt.pageY - canvas.offsetTop); + dragStart = ctx.transformedPoint(lastX,lastY); + dragged = false; + } + },false); + canvas.addEventListener('mousemove',function(evt){ + lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft); + lastY = evt.offsetY || (evt.pageY - canvas.offsetTop); + dragged = true; + if (dragStart){ + var pt = ctx.transformedPoint(lastX,lastY); + ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y); + redraw(); + } + },false); + canvas.addEventListener('mouseup',function(evt){ + if (evt.button == 1 || 1 == evt.button&2){ + dragStart = null; + if (dragged) { + + let point = ctx.transformedPoint( + evt.clientX - canvas.offsetLeft, + evt.clientY - canvas.offsetTop + ); + } else { + let point = { + x: Math.floor(ctx.transformedPoint(lastX,lastY).x) * 4, + y: Math.floor(ctx.transformedPoint(lastX,lastY).y) * 4, + }; + x = point.x; y = point.y; + let pixelNumber; + if (y > 0) + pixelNumber = (y) * canvas.width + x + if (y == 0) + pixelNumber = x + + let color = { + r: imgData.data[pixelNumber + 0], + g: imgData.data[pixelNumber + 1], + b: imgData.data[pixelNumber + 2] + }; + + changeColor(rgbToHex(color.r, color.g, color.b)); + } + } else if (evt.button == 0) { + let point = { + x: Math.floor(ctx.transformedPoint(lastX,lastY).x) * 4, + y: Math.floor(ctx.transformedPoint(lastX,lastY).y) * 4, + }; + let rgbColor = hexToRgb(currentColor); + let pixel = JSON.stringify({ + "x": `${point.x/4}`, + "y": `${point.y/4}`, + "r": `${rgbColor.r}`, + "g": `${rgbColor.g}`, + "b": `${rgbColor.b}` + }); + let packet = { + "code": 1, + "content": pixel + } + socket.send(JSON.stringify(packet)); + // console.log(`{\"code\":1, \"content\":${pixel}}`) + + drawPixel(point.x, point.y, undefined); + } + },false); + + var scaleFactor = 1.1; + var zoom = function(clicks){ + var pt = ctx.transformedPoint(lastX,lastY); + ctx.translate(pt.x,pt.y); + var factor = Math.pow(scaleFactor,clicks); + ctx.scale(factor,factor); + ctx.translate(-pt.x,-pt.y); + redraw(); + } + + var handleScroll = function(evt){ + var delta = evt.wheelDelta ? evt.wheelDelta/40 : evt.detail ? -evt.detail : 0; + if (delta) zoom(delta); + return evt.preventDefault() && false; + }; + canvas.addEventListener('DOMMouseScroll',handleScroll,false); + canvas.addEventListener('mousewheel',handleScroll,false); +}; + +function evaulatePixelNumber(x, y) { + let pixelNumber; + if (y > 0) + pixelNumber = (y) * canvas.width + x + if (y == 0) + pixelNumber = x + return pixelNumber +} +function changeColor(color) { + if (color == undefined) currentColor = colorInput.value; + else { + currentColor = color + colorInput.value = color + } +} + + +//Code from https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#5624139 +function hexToRgb(hex) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} + +const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => { + const hex = x.toString(16) + return hex.length === 1 ? '0' + hex : hex +}).join('') + +function trackTransforms(ctx){ + var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg'); + var xform = svg.createSVGMatrix(); + ctx.getTransform = function(){ return xform; }; + + var savedTransforms = []; + var save = ctx.save; + ctx.save = function(){ + savedTransforms.push(xform.translate(0,0)); + return save.call(ctx); + }; + var restore = ctx.restore; + ctx.restore = function(){ + xform = savedTransforms.pop(); + return restore.call(ctx); + }; + + var scale = ctx.scale; + ctx.scale = function(sx,sy){ + xform = xform.scaleNonUniform(sx,sy); + return scale.call(ctx,sx,sy); + }; + var rotate = ctx.rotate; + ctx.rotate = function(radians){ + xform = xform.rotate(radians*180/Math.PI); + return rotate.call(ctx,radians); + }; + var translate = ctx.translate; + ctx.translate = function(dx,dy){ + xform = xform.translate(dx,dy); + return translate.call(ctx,dx,dy); + }; + var transform = ctx.transform; + ctx.transform = function(a,b,c,d,e,f){ + var m2 = svg.createSVGMatrix(); + m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f; + xform = xform.multiply(m2); + return transform.call(ctx,a,b,c,d,e,f); + }; + var setTransform = ctx.setTransform; + ctx.setTransform = function(a,b,c,d,e,f){ + xform.a = a; + xform.b = b; + xform.c = c; + xform.d = d; + xform.e = e; + xform.f = f; + return setTransform.call(ctx,a,b,c,d,e,f); + }; + var pt = svg.createSVGPoint(); + ctx.transformedPoint = function(x,y){ + pt.x=x; pt.y=y; + return pt.matrixTransform(xform.inverse()); + } +} \ No newline at end of file