什麼是TogetherJS?
我們來介紹一下TogetherJS,一個從Mozilla實驗室出來的實時協作工具。
TogetherJS是這樣的一種服務,你能為一個已經存在的網站增加實時協作特性。使用這種工具,兩個或者更多的網站或者web應用訪問者能夠看到別人滑鼠位置,單擊,追蹤他人的瀏覽記錄,一起編輯表單,觀看視訊,還能夠通過聲音以及WebRTC聊天。
TogetherJS包括這樣一些特性:
- 檢視他人的滑鼠和點選情況。
- 檢視滾動位置。
- 觀察某人瀏覽過的頁面。
- 文字聊天。
- 通過WebRTC語音聊天。
- 表單域同步(文字域,核取方塊等等)。
- 同步播放/暫停/追蹤視訊。
- 同一網站跨多個頁面延續會話。
如何整合
許多TogetherJS的特性無需更改你的網站。TogetherJS瀏覽DOM,並決定許多應該做什麼—檢測表單域,一些諸如CodeMirror和Ace的編輯器,以及在你的頁面注入工具條。
要想嘗試TogetherJS,僅僅要做的是把這個新增到你的頁面裡:
1 |
<script src="https://togetherjs.com/togetherjs.js"></script> |
然後建立一個按鈕,讓你的使用者開始TogetherJS:
1 2 3 4 5 |
<button id="collaborate" type="button">Collaborate</button> <script> document.getElementById("collaborate") .addEventListener("click", TogetherJS, false); </script> |
如果你想看一些Together做了什麼,jsFiddle已經啟用了TogetherJS:
只需要單擊下Collaboration,就會啟動TogetherJS了。你也可以自如地使用TogetherJS,下面我們會講到。
擴充套件你的應用
TogetherJS可以通過瀏覽DOM來解決一些事情,但不能同步你的JavaScript應用。比如,在你的應用中有一些條目是通過JavaScript來更新的,那麼它們就不會相互間自動同步。有時人們期望能自動更新,但即使做了跨頁面間的DOM同步,我們也不可能會做到同步底層的JavaScript物件。不像有些產品,如Firebase或者谷歌Drive實時API,TogetherJS沒有賦予你實時的永續性。網站永續性這樣的功能是由你決定,我們僅僅只是在瀏覽器中同步會話而已。
我們使用了一個簡單的繪畫應用來舉例。我們已經發布了完整的例子作為模板,你可以派生以及親自體驗。
一個非常小的繪畫應用
我們開始一個非常簡單的繪畫程式,我們有一個簡單的畫布:
1 2 3 |
<canvas id="sketch" style="height: 400px; width: 400px; border: 1px solid #000"> </canvas> |
然後是一些設定:
1 2 3 4 5 6 7 8 9 |
// 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()處理程式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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()函式就會計算出需要繪畫的線條:
1 2 3 4 5 6 7 8 |
function move(e) { var mouse = { x: e.pageX - this.offsetLeft, y: e.pageY - this.offsetTop }; draw(lastMouse, mouse); lastMouse = mouse; } |
最後是繪畫線條的函式:
1 2 3 4 5 6 7 |
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也能讓應用傳送自己的訊息,如這樣傳送訊息(每個訊息必須有一個型別):
1 2 3 4 |
TogetherJS.send({ type: "message-type", ...any other attributes you want to send... }) |
然後這樣去監聽:
1 2 3 4 5 6 7 |
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自己的訊息。
為了要同步繪畫中我們想觀看的任意一條正在畫的線,並且把這些傳送給其它人:
1 2 3 4 5 6 7 8 9 10 11 |
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)。我們傳送的訊息應該要一目瞭然的。
下面,我們要去監聽這些訊息:
1 2 3 4 5 6 |
TogetherJS.hub.on("draw", function (msg) { if (! msg.sameUrl) { return; } draw(msg.start, msg.end); }); |
當我們註冊這個監聽器時,我們不必擔心TogetherJS是否正在執行,因為只有在它在執行時才能被呼叫。
這樣足夠讓我們的繪畫更生動並且協作的。但我們還缺少一個:如果我開始畫一個影像,然後你加入了我,你僅僅會看到我畫的新的線條,你看不到我已經畫過的影像。
為了要解決這個,我們會去監聽togertherjs.hello訊息,它在每個客戶端首次訪問一個新的頁面時傳送。當我們監聽到這個訊息時,我們會傳送我們的畫布上的影像給其他人。
1 2 3 4 5 6 7 8 9 10 |
TogetherJS.hub.on("togetherjs.hello", function (msg) { if (! msg.sameUrl) { return; } var image = canvas.toDataURL("image/png"); TogetherJS.send({ type: "init", image: image }); }); |
現在我們只要去監聽新的init訊息:
1 2 3 4 5 6 7 8 |
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的#togetherjs上聯絡我們。irc.mozilla.org
在Github上查詢程式碼,如果你遇到bug或者有特性請求,請提一個問題。請別害羞,我們對許多種反饋非常感興趣:想法,潛在用例(以及來自這些用例的挑戰),和那些看起來通過文件無法回答的問題(這也同時表示我們文件上的bug)。請告訴我們有關潛在的協同應用。
Twitter上關注我們:@togetherjs。