協作模式:Fabric.js - 同步對象:修改事件到另一個客戶端
什麼是傳播從客戶端#1的畫布客戶#2的畫布變化的最佳方式是什麼?以下是我如何捕獲事件並將其發送到Socket.io的方法。
$scope.canvas.on('object:modified',function(e) {
Socket.whiteboardMessage({
eventId:'object:modified',
event:e.target.toJSON()
});
});
在接收端,此代碼的工作出色添加新對象到屏幕上,但我無法找到如何選擇和更新在畫布上的現有對象的文檔。
fabric.util.enlivenObjects([e.event], function(objects) {
objects.forEach(function(o) {
$scope.canvas.add(o);
});
});
我沒看到,對象有個人setter和一個大容量二傳手,但我無法弄清楚如何選擇基於事件數據的現有對象。
在理想情況下,該流程將是:
- 與目標對象數據接收事件。
- 選擇畫布中的現有對象。
- 執行批量更新。
- 刷新畫布。
希望有Fabric.JS經驗的人可以幫我弄清楚這一點。謝謝!
UPDATED ANSWER - Thanks AJM!
AJM爲每個新創建的元素建議一個唯一的ID是正確的。我也能夠爲所有新創建的繪圖路徑創建一個新的ID。下面是它如何工作的:
var t = new fabric.IText('Edit me...', {
left: $scope.width/2-100,
top: $scope.height/2-50
});
t.set('id',randomHash());
$scope.canvas.add(t);
我還抓獲了新創建的路徑,並增加了ID:
$scope.canvas.on('path:created',function(e) {
if (e.target.id === undefined) {
e.target.set('id',randomHash());
}
});
不過,我遇到了一個問題,我的ID是在控制檯日誌中可見的,但它是不存在執行object.toJSON()
後。這是因爲Fabric有自己的序列化方法,可以將數據細分爲標準化的屬性列表。以包括額外的屬性,我不得不序列化數據運輸像這樣:
$scope.canvas.on('object:modified',function(e) {
Socket.whiteboardMessage({
object:e.target.toJSON(['id']) // includes "id" in output.
})
});
現在,每個對象具有用於執行更新的唯一ID。在我的代碼的接收端,我添加了AJM的對象查找功能。我把這個代碼我的應用程序的「啓動」一節中,因此將只運行一次(Fabric.js加載後,當然!)
fabric.Canvas.prototype.getObjectById = function (id) {
var objs = this.getObjects();
for (var i = 0, len = objs.length; i < len; i++) {
if (objs[i].id == id) {
return objs[i];
}
}
return 0;
};
現在,每當一個新的套接字。IO消息被接收與白板數據,我可以通過這條線找到它在畫布:
var obj = $scope.canvas.getObjectById(e.object.id);
插入和取出都方便,但對於更新的代碼這最後一塊沒有的伎倆:
obj.set(e.object); // Updates properties
$scope.canvas.renderAll(); // Redraws canvas
$scope.canvas.calcOffset(); // Updates offsets
所有這些都要求我處理以下事件。路徑一旦創建就被視爲對象。
$scope.canvas.on('object:added',function(e) { });
$scope.canvas.on('object:modified',function(e) { });
$scope.canvas.on('object:moving',function(e) { });
$scope.canvas.on('object:removed',function(e) { });
$scope.canvas.on('path:created',function(e) { });
有趣,謝謝你的提示。你是如何解決將id添加到自由繪製模式下生成的路徑的?這聽起來像你使用路徑:添加並分配一個ID,如果它還沒有一個......是否正確? –
不幸的是,我們不需要在我們的應用程序中支持免費的繪圖,所以我無法回答那個問題(我在應用程序的一側停放了一個包含形狀,箭頭,圖像和幾個文本對象的「調色板」我創建的;我可以基本保證除自由繪製路徑以外的任何東西)。冒着猜測,但只要路徑具有唯一的ID屬性(即在那裏或您設置的),所有的*應該*工作相同(您可以通過ID選擇它們,然後應用適當的突變)。 – ajm
繪圖的工作方式與對象完全相同,除了我必須偵聽路徑:爲了設置ID而創建的。我用全套代碼更新了我的答案。 –