简介:
我正在建立一个网站,其主要功能之一是白板。您可以与其他用户打开一个 session ,然后您在板上绘制的任何内容他都会看到,反之亦然。
使用 HTML 和 javascript 点对点实现。
问题:
现在有两件事可以触发你在板上绘图 - 你画一些东西或者你在 session 中的伙伴画一些东西。 (两者都会触发绘图事件)。
当你画一些东西,同时你的伙伴也画一些东西时,问题就开始了。 (图纸是混合的,我的输入和我的伙伴收到的是混合的,不能并行处理两个图纸输入)
解决办法:(?)
多线程可以解决这个问题。在单独的线程中处理合作伙伴的绘图。然而,JavaScript 不是多线程的。 我读到了有关使用“worker”(HTML 5)的选项,但如果我理解正确的话,它在处理主线程中的变量方面非常有限,并且不能影响 HTML(更改屏幕上看到的内容)。
有什么想法吗?
最佳答案
多线程无法为您解决这个问题。正如已经提到的,Web Workers 是有限的,并且不会在这种情况下增加任何好处,因为这需要访问 DOM 等(您可以使用它们来使用可传输对象(即类型化数组)处理像素,但你必须在处理后将它们通过管道返回到你的主 JS 线程,这样你就可以做到这一点)。
好消息是,您可以同时绘制两幅不同的画作。我假设您使用 Canvas 来实现此目的。
只需创建两个重叠的 Canvas ,并将本地鼠标/触摸移动传送到其中一个 Canvas ,同时通过网络套接字将数据传送到另一个 Canvas 。
另一种方法是以原子方式绘制每个段 - 对于每次鼠标移动以及通过网络套接字接收到的表示一次移动的每个数据(您可能需要在此处进行迭代),例如:
ctx.beginPath(); /// reset path for this segment
ctx.moveTo(oldX, oldY); /// of current client/user
ctx.lineTo(x, y); /// current position
ctx.strokeStyle = currentColor; /// the one drawing this line
ctx.stroke();
(oldX/Y 将由鼠标按下事件第一次初始化)。
以分段方式执行此操作允许两者同时绘制,尽管这对性能要求更高。如果行的顺序不重要,我个人会选择分层 Canvas 解决方案。由于您的解决方案将使用事件,因此它将是异步的,并且会处理一个事件队列,该队列在这里应该可以正常工作。
只需设置一些数组来保存每个用户的数据(旧位置、样式等),以便您可以使用当前用户/客户端的 ID/索引。
一些伪代码来简单概述分段方法:
var oldX = [],
oldY = [],
currentColor = [], ...;
...set up clients, arrays, mousedown/up etc.
canvas.onmousemove = function(e) {
var pos = getMousePos ...
if (isDrawing) drawSegment(0, pos.x, pos.y); /// f.ex. client 0 = local
}
function handleSocketData() {
... get x/y from data stream
drawSegment(1, x, y); /// f.ex. client 1 = web socket
}
function drawSegment(client, x, y) {
ctx.beginPath();
ctx.moveTo(oldX[client], oldY[client]);
ctx.lineTo(x, y);
ctx.strokeStyle = currentColor[client];
ctx.stroke();
oldX[client] = x;
oldY[client] = y;
}
这当然是简化的。您需要将每个点存储在点数组中,其状态详细信息与绘制时相同,以便能够在清除时重新绘制 Canvas 、处理套接字上的多个段等等,但我认为它给人一种如何实现的印象该方法的核心原理。
希望这有帮助!
关于javascript - 实现多线程行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21451045/