TogetherJS:Mozilla推出的實時協(xié)作工具
我們來介紹一下TogetherJS,一個從Mozilla實驗室出來的實時協(xié)作工具。
TogetherJS是這樣的一種服務(wù),你能為一個已經(jīng)存在的網(wǎng)站增加實時協(xié)作特性。使用這種工具,兩個或者更多的網(wǎng)站或者web應(yīng)用訪問者能夠看到別人鼠標位置,單擊,追蹤他人的瀏覽記錄,一起編輯表單,觀看視頻,還能夠通過聲音以及WebRTC聊天。
TogetherJS包括這樣一些特性:
- 查看他人的鼠標和點擊情況。
- 查看滾動位置。
- 觀察某人瀏覽過的頁面。
- 文本聊天。
- 通過WebRTC語音聊天。
- 表單域同步(文本域,復選框等等)。
- 同步播放/暫停/追蹤視頻。
- 同一網(wǎng)站跨多個頁面延續(xù)會話。
如何集成
許多TogetherJS的特性無需更改你的網(wǎng)站。TogetherJS瀏覽DOM,并決定許多應(yīng)該做什么–檢測表單域,一些諸如CodeMirror和Ace的編輯器,以及在你的頁面注入工具條。
要想嘗試TogetherJS,僅僅要做的是把這個添加到你的頁面里:
- <script src="https://togetherjs.com/togetherjs.js"></script>
然后創(chuàng)建一個按鈕,讓你的用戶開始TogetherJS:
- <button id="collaborate" type="button">Collaborate</button>
- <script>
- document.getElementById("collaborate")
- .addEventListener("click", TogetherJS, false);
如果你想看一些Together做了什么,jsFiddle已經(jīng)啟用了TogetherJS:
只需要單擊下Collaboration,就會啟動TogetherJS了。你也可以自如地使用TogetherJS,下面我們會講到。
擴展你的應(yīng)用
TogetherJS可以通過瀏覽DOM來解決一些事情,但不能同步你的JavaScript應(yīng)用。比如,在你的應(yīng)用中有一些條目是通過JavaScript來更新的,那么它們就不會相互間自動同步。有時人們期望能自動更新,但即使做了跨頁面間的DOM同步,我們也不可能會做到同步底層的JavaScript對象。不像有些產(chǎn)品,如Firebase或者谷歌Drive實時API,TogetherJS沒有賦予你實時的持久性。網(wǎng)站持久性這樣的功能是由你決定,我們僅僅只是在瀏覽器中同步會話而已。
我們使用了一個簡單的繪畫應(yīng)用來舉例。我們已經(jīng)發(fā)布了完整的例子作為模板,你可以派生以及親自體驗。
一個非常小的繪畫應(yīng)用
我們開始一個非常簡單的繪畫程序,我們有一個簡單的畫布:
- <canvas id="sketch"
- style="height: 400px; width: 400px; border: 1px solid #000">
- </canvas>
然后是一些設(shè)置:
- // 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';
我們使用畫布的mousedown和mouseup事件去為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()函數(shù)就會計算出需要繪畫的線條:
- function move(e) {
- var mouse = {
- x: e.pageX - this.offsetLeft,
- y: e.pageY - this.offsetTop
- };
- draw(lastMouse, mouse);
- lastMouse = mouse;
- }
***是繪畫線條的函數(shù):
- function draw(start, end) {
- context.beginPath();
- context.moveTo(start.x, start.y);
- context.lineTo(end.x, end.y);
- context.closePath();
- context.stroke();
- }
一個簡單的繪畫應(yīng)用,這些代碼就足夠了。現(xiàn)在如果你在你的應(yīng)用中啟用了TogetherJS,你會看到別人頁面在移動,并且能看到他們的鼠標,但你看不到繪畫。讓我們來解決下!
添加TogetherJS
TogetherJS擁有一個交換中心,能在同一會話中相互間回復消息。這并不翻譯消息,只是來回往返,包括消息來自可能在另一頁面。TogetherJS也能讓應(yīng)用發(fā)送自己的消息,如這樣發(fā)送消息(每個消息必須有一個類型):
- TogetherJS.send({
- type: "message-type",
- ...any other attributes you want to send...
- })
然后這樣去監(jiān)聽:
- 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;
- }
- });
消息類型是基于命名空間,以致你的應(yīng)用消息不會意外覆蓋TogetherJS自己的消息。
為了要同步繪畫中我們想觀看的任意一條正在畫的線,并且把這些發(fā)送給其它人:
- 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;
- }
在發(fā)送前,我們應(yīng)該檢查下TogetherJS確實正在運行(TogetherJS.running)。我們發(fā)送的消息應(yīng)該要一目了然的。
下面,我們要去監(jiān)聽這些消息:
- TogetherJS.hub.on("draw", function (msg) {
- if (! msg.sameUrl) {
- return;
- }
- draw(msg.start, msg.end);
- });
當我們注冊這個監(jiān)聽器時,我們不必擔心TogetherJS是否正在運行,因為只有在它在運行時才能被調(diào)用。
這樣足夠讓我們的繪畫更生動并且協(xié)作的。但我們還缺少一個:如果我開始畫一個圖像,然后你加入了我,你僅僅會看到我畫的新的線條,你看不到我已經(jīng)畫過的圖像。
為了要解決這個,我們會去監(jiān)聽togertherjs.hello消息,它在每個客戶端***訪問一個新的頁面時發(fā)送。當我們監(jiān)聽到這個消息時,我們會發(fā)送我們的畫布上的圖像給其他人。
- TogetherJS.hub.on("togetherjs.hello", function (msg) {
- if (! msg.sameUrl) {
- return;
- }
- var image = canvas.toDataURL("image/png");
- TogetherJS.send({
- type: "init",
- image: image
- });
- });
現(xiàn)在我們只要去監(jiān)聽新的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讓我們制作了一個生動的繪畫應(yīng)用。當然,我們也要去編寫些代碼,但這里是一些TogetherJS為我們處理的事情:
提供用戶一個URL與另一個用戶分享去啟動會話。
建立一個WebSocket連接到中心服務(wù)器,提供客戶端之間的信息往返。
讓用戶設(shè)置名稱和頭像,同時觀察其他人也在當前會話中。
保持跟蹤,誰在線,誰離開,還有誰空閑中。
簡單但必須的特性,像可用的文本聊天
會話初始化以及跟蹤是由TogetherJS處理。
有些事情我們并沒在這個例子中做的:
我們使用了固定大小的畫布,所以我們沒去處理不同客戶端和不同的分辨率。通常TogetherJS會處理不同類型的客戶端,并且使用分辨率無關(guān)的定位(甚至對響應(yīng)設(shè)計也有效)。一種修復的方法可能是保證一個固定的長寬比,然后用長寬的百分比去定位繪畫。
我們沒使用任何一個有趣的繪畫工具!可能你不想同步工具—如果我正在使用紅刷筆繪畫,你不能同時使用綠刷筆來繪畫,這樣也沒有理由。
但一些比如清除畫布應(yīng)該要同步。
我們沒有保存或者加載繪畫。一旦繪畫應(yīng)用有保存和加載,你可能得更多地思考下想同步什么。如果我已經(jīng)創(chuàng)建并且保存了一個圖片,然后返回到站點加入你的會話,你的圖像會覆蓋我的嗎?把每個圖像放在唯一的URL能更清晰的表明想去編輯哪個圖像。
想了解更多?
對TogetherJS架構(gòu)好奇?請查閱技術(shù)簡介。
在jsFiddle上嘗試TogetherJS。
通過文檔上的按鈕聯(lián)系我們:”提供實時幫助”會請求啟動一個TogetherJS會話
在IRC的#togetherjs上聯(lián)系我們。irc.mozilla.org
在Github上查找代碼,如果你遇到bug或者有特性請求,請?zhí)嵋粋€問題。請別害羞,我們對許多種反饋非常感興趣:想法,潛在用例(以及來自這些用例的挑戰(zhàn)),和那些看起來通過文檔無法回答的問題(這也同時表示我們文檔上的bug)。請告訴我們有關(guān)潛在的協(xié)同應(yīng)用。
原文鏈接:https://hacks.mozilla.org/2013/10/introducing-togetherjs/