我们如何在单独的页面上同步两个canvas元素 [英] How can we sync two canvas element on separate pages

查看:179
本文介绍了我们如何在单独的页面上同步两个canvas元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的情况,我需要复制在另一个页面上的画布,这两个页面都与socket.io连接,所以我有通信渠道。



因为我的研究说,我可以使用 getImageData 获取像素数据并发送到另一个页面,以便页面将绘制这个画布,我会继续发送这个在间隔任何更改都将同步。
(现在我编写代码用于管理20x20像素块,以及任何更改的块将被复制到另一个页面。)



同步意味着我还需要更改以进行同步。



有没有更好的解决方案?同步只有事情在最后一刻更改或不使用 getImageData



[这个画布不是我的,它不会在我的控制,因为我实现浏览解决方案,所以在代理端我将渲染画布,将在我的控制。]

解决方案

使用每个emit传输完整的画布内容是资源密集型



想象一下,发送一个完整的300x300像素的图片,将一张1x1px的矩形图片传送到画布上!



而是将每组绘图命令序列化(==每个 beginPath 到其结尾填充 / stroke )。您可以使用令牌来表示每个绘图命令。



例如...

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

...可以表示为:

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

当然,您可以自定义标记任何特定于您的设计的复杂命令集。



您可以 JSON.toString 。例如,您可以使用单个令牌来移动整个20x20像素块。这个令牌化的命令集并将其广播到其他客户端(==其他页面)。



当客户端收到消息时,可以用 JSON.parse ,并在自己的画布上处理。



一些注释让你开始:




  • 发射可能会丢失,因此序列 timestamp 字段可用于请求丢失的数据包并正确地排序数据包。您可以执行对等数据包管理,但是让服务器处理数据包管理更容易。


  • 某些画布操作不容易序列化。特别地, getImageData 的像素操作不容易序列化(包括使用getImageData的第三方图像过滤器)。


  • p>在实践中,有时需要将所有画布硬重置为最后知道的好内容状态。你可以做到这一点,让所有的画布清除自己,并重新发布所有的命令集,因为开始的时间。为了更高效,让服务器偶尔缓存最后知道的好画布的图像(以及在已知好的之后发出的任何命令集)。这样,您可以根据需要进行硬重置。



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 said that i can use getImageData to get pixel data and send to another page so that page will draw this canvas, and i'll keep sending this in interval so any changes will be synced as well.. (right now i writing code for managing 20x20 pixel blocks and whatever block changed that will copied to another page.)

Sync means i'll also need changes to be sync.

is there any better solution? to sync only things are changed in last moment or without using getImageData.

[this canvas is not mine it will be not in my control, because i am implementing co browsing solution so on agent side i'll render canvas which will be in my control.]

解决方案

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.

这篇关于我们如何在单独的页面上同步两个canvas元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆