Search code examples
angularwebsockethtml5-canvasdrawing

Real time canvas drawing on different screen sizes


I'm trying to create a real time canvas drawing tool (freehand drawing). Example: just one person will draw on a canvas, and his drawing will replicate on a N numbers of clients canvas. The problem is each person has a different size of screen and I need to scale accordinly. I can trasmite the drawing points in real time and replicate then in the client, but I can't figure out how to scale the points without distortion and in the exactly same place (I have a background image and I made an overlay with the canvas element, so if a drawing its not at the same position as the person that is drawing, it becomes evident that the scale is not right).

 // I have an observable that will receive the coordinates (coord[])
 // generated by the person who is responsible for the drawing.
 // The code below will only be executed for the person, who is 
 // watching, I can't figure out how to scale on the client screen...
 let currentX = parseFloat(coord[0]);
 let currentY = parseFloat(coord[1]);


 // if there is no previous points, then i'm starting at -1
 if (prevX == -1.0) {
    prevX = currentX;
 }

 if (prevY == -1.0) {
     prevY = currentY;
 }

 let pX = prevX * this.canvasEl.width/this.canvasEl.clientWidth;
 let pY = prevY * this.canvasEl.height/this.canvasEl.clientHeight;
 let cX = currentX * this.canvasEl.width/this.canvasEl.clientWidth;
 let cY = currentY * this.canvasEl.height/this.canvasEl.clientHeight;

 this.cx.beginPath();
 this.cx.moveTo(pX, pY);
 this.cx.lineTo(cX, cY);
 this.cx.stroke();

 prevX = currentX;

Solution

  • If you also transmit the size of the original canvas then you can work out a scale factor on other devices.

    let scale = localCanvas.width / originalCanvas.width;
    

    Then use this scale factor for all drawing.

    context.moveTo(coord.x * scale, coord.y * scale);
    context.lineTo(nextCoord.x * scale, nextCoord.y * scale);
    

    This assumes the canvas sizes are proportional and the background fits exactly behind the canvas element.