How can we sync two canvas element on separate pages

前端 未结 2 1921
粉色の甜心
粉色の甜心 2021-01-17 01:58

I am situation where i need to copy canvas on another page, both those pages are connected with socket.io so i\'ve communication channel.

i as far as i my research s

相关标签:
2条回答
  • 2021-01-17 02:12

    Transporting the full canvas content with each emit is resource intensive & inefficient.

    Imagine sending a full 300x300px image to convey a single 1x1px rect drawn onto the canvas!

    Instead, serialize each set of drawing commands (==each beginPath through its ending fill / stroke). You can use tokens to represent each drawing command.

    For example...

    ctx.beginPath();
    ctx.moveTo(100,50);
    ctx.lineTo(150,100);
    ctx.lineTo(50,100);
    ctx.closePath();
    ctx.fillStyle='red';
    ctx.fill();
    

    ... can be tokenized as:

    var set1=[
        ['m',100,50],
        ['l',150,100],
        ['l',50,100],
        ['z'],
        ['fs','red'],
        ['f'],
        ['sequence',myOrder++],
        ['timestamp',performance.now()]
    ];
    

    Of course, you can custom tokenize any complex command sets that are specific to your design. For example, you might have a single token that moves an entire 20x20 pixel block.

    You can JSON.toString this tokenized command set and broadcast it to other clients (==other pages).

    When a client receives a message they can rehydrate the command set with JSON.parse and process it on their own canvas.

    A few notes to get you started:

    • Emits can be lost so the sequence and timestamp fields can be used to request missing packets and to properly order packets. You can do peer-to-peer packet management, but it's easier to have the server handle packet management.

    • Some canvas actions are not easily serializable. In particular, pixel manipulations with getImageData are not easily serializable (including 3rd party image filters using getImageData).

    • In practice, you will sometimes need to "hard reset" all canvases to a "last known good" content-state. You could do this by having all canvases clear themselves and reissuing all command sets since the-beginning-of-time. To be more efficient, have the server occasionally cache an image of the last-known-good canvas (and any command sets issued after the known good). This way you can hard-reset if needed.

    0 讨论(0)
  • 2021-01-17 02:20

    Depending on how big your canvas is and how often you are drawing, it might be cheaper to just use canvas.toBlob or canvas.toDataURLand send the entire canvas.

    Checking your entire canvas for changes using getImageData can be quite expensive since you have to iterate over every pixel. If you're changing most of the canvas each time, I'd at least test sending the entire canvas using canvas.toDataURL to send a base64 encoded version.

    0 讨论(0)
提交回复
热议问题