介绍 TogetherJS

什么是 TogetherJS?

我们想介绍一下 TogetherJS,这是一款来自 Mozilla Labs 的实时协作工具。

TogetherJS 是一种服务,您可以将其添加到现有网站以添加实时协作功能。使用该工具,网站或 Web 应用程序上的两个或多个访问者可以相互看到对方的鼠标/光标位置、点击、跟踪彼此的浏览、一起编辑表单、一起观看视频,以及通过音频和 WebRTC 进行聊天。

TogetherJS 包含的一些功能

  • 查看他人的光标和点击
  • 查看滚动位置
  • 观看一个人在页面上访问的页面
  • 文字聊天
  • 使用 WebRTC 进行音频聊天
  • 表单字段同步(文本字段、复选框等)
  • 同步播放/暂停/跟踪视频
  • 跨站点多个页面继续会话

如何集成

TogetherJS 的许多功能不需要修改您的网站。TogetherJS 会查看 DOM 并确定它应该做的事情 - 它检测表单字段、检测一些编辑器,如 CodeMirrorAce,并将它的工具栏注入您的页面。

要试用 TogetherJS,您只需要将以下代码添加到您的页面


然后为您的用户创建一个按钮来启动 TogetherJS



如果您想了解 TogetherJS 的部分功能,jsFiddle 已经启用了 TogetherJS

jsfiddle with Collaborate highlighted

只需点击 **协作** 即可启动 TogetherJS。您也可以在自己的 fiddles 中使用 TogetherJS,如下所示。

扩展您的应用程序

TogetherJS 可以通过查看 DOM 来找出一些东西,但它不能同步您的 JavaScript 应用程序。例如,如果您在应用程序中有一个通过 JavaScript 更新的项目列表,该列表不会自动同步到两个用户。有时人们期望(或者至少希望)它会自动更新,但即使我们确实跨两个页面同步了 DOM,我们也无法同步您的底层 JavaScript 对象。与 FirebaseGoogle Drive Realtime API 这样的产品不同,TogetherJS 不会为您提供实时持久性 - 您的持久性和网站的功能由您自己决定,我们只是在浏览器本身中同步会话。

因此,如果您有一个丰富的 JavaScript 应用程序,您将不得不编写一些额外的代码来保持会话同步。不过,我们努力让它更容易!

举个例子,我们想使用一个简单的绘图应用程序。我们发布了 完整的示例作为 fiddle,您可以自行分叉和玩耍。

一个非常小的绘图应用程序

我们从一个非常简单的绘图程序开始。我们有一个简单的画布



然后是一些设置

// get the canvas element and its context
var canvas = document.querySelector('#sketch');
var context = canvas.getContext('2d');

// brush settings
context.lineWidth = 2;
context.lineJoin = 'round';
context.lineCap = 'round';
context.strokeStyle = '#000';

我们将使用画布上的 mousedownmouseup 事件来注册我们对 mousemove 事件的 move() 处理程序

var lastMouse = {
  x: 0,
  y: 0
};

// attach the mousedown, mousemove, mouseup event listeners.
canvas.addEventListener('mousedown', function (e) {
    lastMouse = {
        x: e.pageX - this.offsetLeft,
        y: e.pageY - this.offsetTop
    };
    canvas.addEventListener('mousemove', move, false);
}, false);

canvas.addEventListener('mouseup', function () {
    canvas.removeEventListener('mousemove', move, false);
}, false);

然后 move() 函数将找出需要绘制的线条

function move(e) {
    var mouse = {
        x: e.pageX - this.offsetLeft,
        y: e.pageY - this.offsetTop
    };
    draw(lastMouse, mouse);
    lastMouse = mouse;
}

最后是一个绘制线条的函数

function draw(start, end) {
    context.beginPath();
    context.moveTo(start.x, start.y);
    context.lineTo(end.x, end.y);
    context.closePath();
    context.stroke();
}

这足以让我们得到一个非常简单的绘图应用程序。此时,如果您在此应用程序上启用 TogetherJS,您将看到对方移动并看到他们的鼠标光标和点击,但您不会看到绘图。让我们解决这个问题!

添加 TogetherJS

TogetherJS 有一个“集线器”,它在会话中的每个人之间回显消息。它不解释消息,并且所有消息都来回传递,包括来自可能在另一个页面上的用户的消息。TogetherJS 还允许应用程序发送自己的消息,例如

TogetherJS.send({
  type: "message-type",
  ...any other attributes you want to send...
})

发送消息(每条消息必须有一个 type),以及监听

TogetherJS.hub.on("message-type", function (msg) {
  if (! msg.sameUrl) {
    // Usually you'll test for this to discard messages that came
    // from a user at a different page
    return;
  }
});

消息类型是带命名空间的,因此您的应用程序消息不会意外地与 TogetherJS 自己的消息重叠。

为了同步绘图,我们希望监视任何正在绘制的线条并将它们发送给其他对等方

function move(e) {
    var mouse = {
        x: e.pageX - this.offsetLeft,
        y: e.pageY - this.offsetTop
    };
    draw(lastMouse, mouse);
    if (TogetherJS.running) {
        TogetherJS.send({type: "draw", start: lastMouse end: mouse});
    }
    lastMouse = mouse;
}

在发送之前,我们检查 TogetherJS 是否正在运行(TogetherJS.running)。我们发送的消息不言而喻。

接下来,我们必须监听消息

TogetherJS.hub.on("draw", function (msg) {
    if (! msg.sameUrl) {
        return;
    }
    draw(msg.start, msg.end);
});

当我们注册此监听器时,我们不必担心 TogetherJS 是否正在运行,它只能在 TogetherJS 运行时被调用。

这足以使我们的绘图变得实时和协作。但我们缺少一个东西:如果我开始绘制图像,而你加入我,你只会看到我绘制的线条,你不会看到我已经绘制的图像。

为了解决这个问题,我们将监听 togetherjs.hello 消息,这是每个客户端在第一次到达新页面时发送的消息。当我们看到该消息时,我们将向对方发送我们画布的图像

TogetherJS.hub.on("togetherjs.hello", function (msg) {
    if (! msg.sameUrl) {
        return;
    }
    var image = canvas.toDataURL("image/png");
    TogetherJS.send({
        type: "init",
        image: image
    });
});

现在,我们只需监听这个新的 init 消息

TogetherJS.hub.on("init", function (msg) {
    if (! msg.sameUrl) {
        return;
    }
    var image = new Image();
    image.src = msg.image;
    context.drawImage(image, 0, 0);
});

只用几行代码,TogetherJS 就让我们创建了一个实时绘图应用程序。当然,我们必须做一些代码,但以下是一些 TogetherJS 为我们处理的事情

  • 为用户提供一个 URL,与另一个用户共享以启动会话 邀请窗口截图
  • 建立到我们 集线器服务器 的 WebSocket 连接,该连接在客户端之间来回回显消息
  • 允许用户设置他们的姓名和头像,并查看还有谁在会话中 头像/姓名设置截图
  • 跟踪谁可用、谁已离开以及谁处于空闲状态
  • 简单的但必要的特性,如文本聊天可用 聊天窗口截图
  • 会话初始化和跟踪由 TogetherJS 处理

我们在本示例中没有做的一些事情

  • 我们使用了一个固定大小的画布,这样我们就不必处理两个客户端和两个不同的分辨率。通常,TogetherJS 会处理不同类型的客户端和使用与分辨率无关的定位(甚至适用于响应式设计)。解决此问题的一种方法可能是确保固定纵横比,然后使用高度/宽度的百分比来表示所有绘图位置。
  • 我们没有任何有趣的绘图工具!您可能不想同步工具本身 - 如果我用红色画笔绘制,那么您没有理由不能同时用绿色画笔绘制。
  • 但清除画布之类的事情应该同步。
  • 我们不保存或加载任何绘图。一旦绘图应用程序有了保存和加载功能,您可能必须更多地考虑要同步的内容。如果我创建了一张图片,保存了它,然后返回到网站加入您的会话,您的图像会覆盖我的图像吗?将每个图像放在唯一的 URL 上将使每个人要编辑哪个图像更加清晰。

想了解更多吗?

  • 对 TogetherJS 的架构感兴趣吗?阅读 技术概述
  • 在 jsFiddle 上试用 TogetherJS
  • 通过 文档中的按钮 找到我们:“获取实时帮助”,它将要求与我们其中一位开始 TogetherJS 会话。
  • 在 irc.mozilla.org 的 #togetherjs 上通过 IRC 找到我们。
  • GitHub 上找到代码,如果您发现错误或有功能请求,请 打开一个问题。不要害羞,我们对各种形式的问题反馈感兴趣:想法、潜在用例(以及来自这些用例的挑战)、通过我们的文档似乎没有得到解答的问题(每个问题也暗示了我们文档中的错误)、告诉我们可能协同的应用程序。
  • 在 Twitter 上关注我们:@togetherjs

您希望在哪些类型的网站上看到 TogetherJS?我们很乐意在评论区听到您的想法。

关于 Robert Nyman [荣誉编辑]

Mozilla Hacks 的技术布道者和编辑。发表关于 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直在从事 Web 前端开发工作 - 在瑞典和纽约市。他经常在 http://robertnyman.com 上写博客,并且喜欢旅行和结识新朋友。

更多 Robert Nyman [荣誉编辑] 的文章…


35 条评论

  1. Phil Leggetter

    这很棒。我认为我们需要看到实时网页技术的创新,而协作是其主要用例。目前,我们在编辑文档(如 Google Docs 和 Cloud9 IDE)、共享敏捷/Scrum 看板和待办事项列表方面似乎遇到了瓶颈。并不是说这些不好用,它们非常有用。只是它们已经存在了一段时间,我想看看接下来会发生什么。

    是否值得澄清 TogetherJS 的浏览器支持?

    例如,简要检查代码表明

    * WebRTC 要求
    * 它似乎需要 WebSocket 支持,并且没有基于 HTTP 的回退

    原因是 TogetherJS 似乎允许 *任何人* 将其添加到自己的网站。但如果“安装程序”没有意识到这些要求,他们可能经常会想知道为什么有些用户没有获得预期的功能。

    也许 TogetherJS 提供回调以指示何时不存在要求之一或无法连接到 Hub?

    2013 年 10 月 16 日 下午 03:05

    1. Robert Nyman [编辑]

      感谢您的赞赏!

      关于网页浏览器支持,它在 TogetherJS 的文档 中有说明。关于警告实施者的想法很有趣,可能值得添加。

      2013 年 10 月 16 日 下午 03:15

    2. Ian Bicking

      我们确实尝试在浏览器缺乏必要支持时弹出相应的错误消息。(使用 TogetherJS 不需要 WebRTC,只有使用音频聊天才需要,因此如果您尝试在没有 WebRTC 的情况下激活该功能,就会弹出错误消息。)

      还有一个开放的工单,用于向网站开发者公开浏览器支持:https://github.com/mozilla/togetherjs/issues/776

      2013 年 10 月 16 日 下午 08:11

  2. Ivan Dejanovic

    说我感到震惊是轻描淡写。在我们公司开发的最新网页产品中,我们使用 OpenFire 实施了聊天支持。您设法仅使用 JavaScript 实施了聊天、视频和音频。最好的地方在于它非常容易集成到现有产品中。由于 TogetherJS 使用的是 Mozilla 服务器,我可能永远无法在工作中使用它,但我一定会尝试在我的私人项目中使用它。期待看到 TogetherJS 的旅程将网页带到哪里。

    2013 年 10 月 16 日 下午 12:34

    1. Robert Nyman [编辑]

      感谢 Ivan,我们希望您能找到它的用处!

      2013 年 10 月 16 日 下午 13:05

    2. Ian Bicking

      您可以设置自己的服务器:https://togetherjs.com/docs/contributing.html#hosting-the-hub-server

      此外,应该可以使用不同类型的服务器。例如,有一个实验是用 Firebase 替换它:https://github.com/firebase/togetherjs - 我希望我们能够将它推广开来。

      2013 年 10 月 17 日 下午 11:34

  3. Eleftherios Kosmas

    说实话,我很想在 etherpad lite 上看到它。

    2013 年 10 月 16 日 下午 13:45

    1. Marcel Dupont

      我赞成,那将是太棒了。

      或者只是聊天也会很棒。

      2013 年 10 月 16 日 下午 15:04

  4. Ben Werdmuller

    这可能意义重大。就像您讨论的那样,商业协作是一个主要的用例,也可能是它最常用的地方 - 但在很多方面,我期待着第一个用它编写的游戏。它还可以为新类型的讨论平台打开大门。

    2013 年 10 月 16 日 下午 14:57

    1. Robert Nyman [编辑]

      感谢 Ben - 当然,它在游戏中会非常有趣!

      2013 年 10 月 17 日 下午 00:50

  5. Brett Zamir

    非常令人兴奋!我非常希望我们能很快看到完整的屏幕共享和控制功能...

    如果您想允许用户从桌面上的任何位置打开本地文件并以文件类型感知的方式将其公开到网页应用中,以便像 Together.js 那样进行协作查看或编辑(例如,用于编辑 HTML、SVG、JavaScript 或自定义文件类型文件等),您可以查看 WebAppFind,网址为 https://github.com/brettz9/webappfind(目前仅限 Windows)。

    虽然我可能会让一个与 Together.js 协作的演示运行起来,但我预计在改进 WebAppFind 以及完成 ExecuteBuilder 上会忙一段时间,ExecuteBuilder 是另一个附加组件,旨在促进构建可由 WebAppFind 使用的可执行文件,并具有在单独的任务栏实例中(通过单独的配置文件)打开网页应用的功能,从而模仿以前的 Prism 项目行为。所以,如果有人急于让它尽快运行起来,那就请自便吧!不仅允许像 WebAppFind 那样对本地 HTML/SVG/图像文件进行所见即所得的文字处理,而且还具有 Together.js 的协作功能,这将非常酷。

    (我还希望将 WebAppFind 的功能添加到文件浏览器增强版中:https://addons.mozilla.org/en-US/firefox/addon/filebrowser-enhanced/,以便用户能够通过 Firefox 自身的桌面浏览页面在网页应用中打开本地文件)。

    欢迎通过问题跟踪器报告想法或提交拉取请求!

    2013 年 10 月 16 日 下午 16:39

    1. Robert Nyman [编辑]

      感谢您的提醒,Brett!

      2013 年 10 月 17 日 下午 00:50

  6. Mike Conley

    嗨!我们能够将 TogetherJS 添加到 Review Board(基于网页的代码审查工具)的扩展程序中。

    这是一个演示视频:http://www.youtube.com/watch?v=tEfbREmTBjc

    我们非常兴奋地看到,使用 TogetherJS 等技术可以将代码审查变得更加协作。继续努力!

    -Mike

    2013 年 10 月 16 日 下午 20:06

    1. Robert Nyman [编辑]

      看起来很棒,感谢分享!

      2013 年 10 月 17 日 下午 00:51

    2. Ian Bicking

      扩展程序是否已发布?或者从 https://github.com/mozilla/togetherjs/wiki/Libraries-and-Plugins 中链接它(我已经将您的视频发布在那里)

      2013 年 10 月 17 日 下午 11:27

      1. Mike Conley

        我已经编辑了维基,以包含指向 GH 存储库的链接。谢谢!

        2013 年 10 月 18 日 下午 12:26

  7. Jelle Akkerman

    如何将其做成浏览器扩展程序,以便您可以在每个网站上启用 together.js?:) 单击浏览器扩展程序,together.js 就会注入页面,与朋友共享链接,together.js 就会注入到他们的页面中。

    2013 年 10 月 17 日 下午 01:18

    1. Samuel Bosch

      我刚刚有了完全相同的想法。今晚回家后我会试试。

      2013 年 10 月 17 日 下午 01:35

    2. Ian Bicking

      有一个 Chrome 扩展程序 https://github.com/zhuzhuor/TowTruck.crx(可能已过时,我不确定),以及存储库中为 Firefox 提供的粗略附加组件。还有一个我不知该如何处理的拉取请求,用于另一个 Chrome 扩展程序:https://github.com/mozilla/togetherjs/pull/595

      最终,我担心使用附加组件不会带来很好的体验。就像绘图应用程序如果没有一些集成就不起作用一样,我认为在很多网站上都会有类似的体验。

      2013 年 10 月 17 日 下午 11:32

  8. Vignesh Swaminathan

    这真是太棒了!有一个问题,如果网页应用打开了新的浏览器选项卡,是否可以继续会话?

    2013 年 10 月 17 日 下午 02:01

    1. Ian Bicking

      新的选项卡中的任何链接都必须在 URL 中包含 #&togetherjs=SESSION_ID。如果您能够将链接重写以包含它,那么是的,会话将在两个选项卡中继续。

      2013 年 10 月 17 日 下午 11:28

      1. Vignesh Swaminathan

        太棒了!

        2013 年 10 月 17 日 下午 21:45

  9. Carlos Cabral

    Mozilla 使用的是哪种 Hub 服务器?它是开源的吗?还是您计划将其作为开源发布?谢谢

    2013 年 10 月 17 日 下午 05:21

    1. Ian Bicking

      您可以在此处了解有关 Hub 的信息:https://togetherjs.com/docs/contributing.html#hosting-the-hub-server

      它不仅是开源的,而且还自行发布了源代码 ;) https://hub.togetherjs.com/server-source

      2013 年 10 月 18 日 下午 12:30

    2. Carlos Cabral

      好吧,我应该在问之前先检查一下 GitHub :)

      2013 年 10 月 18 日 下午 12:47

  10. Bill McCoy

    我不理解关于浏览器支持的文档。虽然没有说明原因,但明确表示 IE 支持不是优先事项,但完全没有提到 Safari,即使 WebSockets 也在上面工作(包括 OS/X 和 iOS)。在 Safari 上支持 TogetherJS 还有其他明显的问题吗?退一步说,这个问题是关于 TogetherJS 在开放网络平台方面的品牌承诺。它被描述为“一个实时协作工具……您可以添加到现有网站”。但谁愿意将不适用于我们一半访客的工具添加到现有网站中呢?我希望在文档中看到明确说明,TogetherJS 的目标是在所有现代浏览器上运行,任何临时问题只是(可以理解的)启动问题。

    2013 年 10 月 17 日 下午 6:00

    1. Ian Bicking

      Safari 确实可以工作,我们没有持续测试它,但它与 Chrome 相似,因此一直相当稳定。我们正在提高 Internet Explorer 的优先级,我们将在 Labs 博客的后续文章中详细讨论:https://blog.mozilla.org/labs/

      2013 年 10 月 18 日 下午 12:29

  11. Phil Wolff

    有人将它打包成 WordPress 小部件了吗?

    2013 年 10 月 17 日 下午 11:16

    1. Ian Bicking

      是的!有两个:https://wordpresstheme.cn/plugins/collaboration/https://wordpresstheme.cn/plugins/wp-togetherjs/

      2013 年 10 月 18 日 下午 12:26

    2. Aaron Druck

      是的,这里有一些插件:https://wordpresstheme.cn/plugins/tags/togetherjs

      2013 年 10 月 18 日 下午 2:03

  12. Arnaud Sahuguet

    太棒了。

    当你将其打包成书签小工具时,它更棒。点击并协作特定页面。
    >>
    var script = document.createElement('script');
    script.setAttribute("type","text/javascript");
    script.setAttribute("src", "https://togetherjs.com/togetherjs.js");
    document.getElementsByTagName("head")[0].appendChild(script);
    setTimeout(function() { TogetherJS(); } , 3000);
    <<
    最小化到
    javascript:(function(){var script=document.createElement('script');script.setAttribute("type","text/javascript");script.setAttribute("src","https://togetherjs.com/togetherjs.js&quot;);document.getElementsByTagName("head")[0].appendChild(script);setTimeout(function(){TogetherJS();},3000);})()

    2013 年 10 月 18 日 下午 12:29

  13. kman

    您好,如果我们不想让 TogetherJS 传递某些表单元素的内容,如何忽略它们?

    2013 年 10 月 18 日 下午 5:52

  14. Shane

    天哪,你们真是太酷了,我们 <3 Mozilla!

    2013 年 10 月 19 日 上午 2:22

  15. James

    您还可以查看 http://www.ucodeme.com,它嵌入了 togtherJS。

    2013 年 10 月 29 日 下午 5:11

  16. dotBuffer

    很棒的工作,很棒的工具,伙计们!

    2013 年 10 月 29 日 下午 10:37

本文的评论已关闭。