我需要在另一个页面上复制画布,这些页面都与socket.io连接,因此我是通信渠道。
我的研究表明,我可以使用getImageData
获取像素数据并发送到另一个页面,以便该页面将绘制此画布,并且我将继续在间隔中发送此内容更改也将同步..
(现在我正在编写用于管理20x20像素块的代码以及将复制到另一个页面的任何块更改。)
同步意味着我还需要进行同步更改。
还有更好的解决方案吗?仅同步事件在最后时刻或不使用getImageData
时更改。
[这个画布不是我的,它不会在我的控制之下,因为我正在实施合作浏览解决方案,所以在代理方面我将渲染画布,这将在我的控制之内。]
答案 0 :(得分:2)
使用每个发射传输完整的画布内容是资源密集型的。效率低下。
想象一下,发送一个完整的300x300px图像来传送画布上绘制的单个1x1px矩形!
相反,序列化每组绘图命令(==每个beginPath
到其结尾fill
/ 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++],
['timestamp',performance.now()]
];
当然,您可以自定义任何特定于您的设计的复杂命令集。例如,您可能只有一个令牌可以移动整个20x20像素块。
您可以JSON.toString
此标记化命令集并将其广播到其他客户端(==其他页面)。
当客户端收到消息时,他们可以使用JSON.parse
对命令集进行补充,并在自己的画布上进行处理。
一些让你入门的笔记:
发送可能会丢失,因此sequence
和timestamp
字段可用于请求丢失的数据包和正确订购数据包。您可以进行点对点数据包管理,但让服务器处理数据包管理更容易。
某些画布操作不易序列化。特别是,使用getImageData
的像素操作不容易序列化(包括使用getImageData的第三方图像过滤器)。
在实践中,您有时需要将所有画布“硬重置”为“最后已知良好”的内容状态。您可以通过让所有画布清除自己并从一开始就重新发布所有命令集来实现此目的。为了提高效率,让服务器偶尔缓存最后已知良好画布的图像(以及在已知商品之后发布的任何命令集)。这样,您可以根据需要进行硬重置。
答案 1 :(得分:1)
根据画布的大小和绘图频率,使用canvas.toBlob
或canvas.toDataURL
并发送整个画布可能更便宜。
使用getImageData
检查整个画布的更改可能非常昂贵,因为您必须迭代每个像素。如果你每次都更换大部分画布,我至少会测试使用canvas.toDataURL
发送整个画布来发送base64编码版本。