# 入门指南
# 快速运行collaboration示例
请参阅 快速运行示例 章节启动服务器,然后在浏览器中打开以下地址以访问collaboration示例:
http://127.0.0.1:8080/examples/UIExtension/collaboration/index.html (opens new window)
# 工作原理
首先,打开API reference,找到collaboration相关的接口和类,如下所示:
其中,关键性的接口是:
CollaborationCommunicator
该接口是浏览器和服务器之间的通信桥梁。它负责连接服务器、创建协作会话、同步数据等。在
/examples/UIExtension/collaboration
目录下,有一个基于communicator的sockjs,您可以参考其具体的实现,以了解更多详细信息。CollabroationDataHandler
假设我们有两个客户端设备:客户端 A 和客户端 B。当客户端 A 创建一个注释时,其相关的注释数据将被发送到服务器,进而将进一步转发给客户端 B。当客户端 B 收到数据时,它会立即根据数据内容重复与客户端 A 相同的操作。此时,数据同步就实现了。客户端 B 的上述操作过程由
CollabroationDataHandler
接口实现,其定义了两种方法:accept(data: CollaborationData): Promise<boolean>
当接收到数据时,该方法将被调用并用于确认当前
CollaborationDataHandler
接口是否需要对数据进行处理。receive(data: CollaborationData, builtinHandler?: CollaborationDataHandler)
当
accept()
方法返回true时,此方法将被调用,并传入两个参数。第一个参数是当前收到的协作数据,第二个是内置数据handler。在某些情况下,您需要决定是否调用内置数据handler。当操作行为没有定义在COLLABORATION_ACTION
时调用了内置数据handler,则会导致不再执行其他同步操作。
CollaborationSessionInfo
当客户端打开 PDF 文件时,它将向服务器发送一个创建新会话的请求。该会话包含当前 PDF 文件的信息以及其唯一标识shareId。通过这种方式,当分享带有shareId的链接给其他用户时,其他用户可以打开此链接并查看原始 PDF 文件,以及启动协作会话。
UserCustomizeCollaborationData
我们的 API 设计允许用户自定义协作操作。您可以通过
PDFViewer.collaborate
API发送自定义协作数据,然后在自定义的CollaborationDataHandler
中接收自定义协作数据以执行同步。COLLABORATION_ACTION
内置协作操作的枚举。
协作如何工作?下面将详细解释整个过程。
备注:Foxit PDF SDK for Web提供的collaboration 示例使用了Node.js作为后端服务器,并使用websocket作为通信通道来建立长时间的协作连接。
客户端A打开PDF文档,其中文档信息将被发送到服务器,并以唯一的shareID发起一个新的会话。在浏览器中,您将看到如下类似的地址:
http://localhost:8080/examples/UIExtension/collaboration/index.html?shareId=2MF8Rp7-Q
客户端A分享协作链接给其他的客户端,这些客户端在打开链接后将被连接到同一台服务器。
例如,客户端A执行创建一个注释的动作,该动作的操作数据将在后台同步发送到服务器,然后转发给其他的客户端。
当其他的客户端收到同步的数据后,Web SDK将找到接收(通过
accept
方法)操作数据的第一个数据handler,并使用CollaborationDataHandler
处理接收的数据,然后在屏幕上输出与客户端 A 相同的操作。
至此,一个完整的协作操作过程已完成!
# 无线循环问题
查看以下代码,首先,注册 DataEvent.annotationAdded
事件,以便在事件触发后发送协作数据。然后,在一个button上注册一个单击事件,通过 PDFPage.addAnnot
API创建注释。调用 PDFPage.addAnnot
方法将触发 DataEvent.annotationAdded
事件。这个逻辑看起来很完美。但是,假设此时有两个客户端 A 和 B。首先单击客户端 A 的按钮并发送协作数据,客户端 B 在收到协作数据后也调用 PDFPage.addAnnot
方法,然后问题就出现了。因为 PDFPage.addAnnot
触发了 DataEvents.annotationAdded
事件,事件回调函数也将发送协作数据,所有客户端在收到协作数据后将继续发送请求。在此过程中,无限循环问题就出现了。
var DataEvents = PDFViewCtrl.PDF.DataEvents;
pdfViewer.eventEmitter.on(DataEvents.annotationAdded, function(annots){
var doc = pdfViewer.getCurrentPDFDoc();
doc.exportAnnotsToJSON(annots).then(function(annotsJSONArray) {
pdfViewer.collaborate(PDFViewCtrl.collab.COLLABORATION_ACTION.CREATE_ANNOT, {
annots: annotsJSONArray
})
});
});
var $button = jQuery('#create-square-button');
$button.on('click', function() {
var doc = pdfViewer.getCurrentPDFDoc();
doc.getPageByIndex(0).then(function(page) {
page.addAnnot({
color: 0xff0000,
rect: { left: 300, right: 400, top: 300, bottom: 200 },
flags: 4,
type: 'square'
});
});
});
var $button = jQuery('#create-line-button');
$button.on('click', function() {
var doc = pdfViewer.getCurrentPDFDoc();
doc.getPageByIndex(0).then(function(page) {
page.addAnnot({
type: 'line',
startStyle: 0,
endStyle: PDF.constant.Ending_Style.Square,
startPoint: {x: 0, y: 0},
endPoint: {x: 100, y: 100},
rect: {
left: 0,
right: 100,
top: 0,
bottom: 100
}
});
});
});
为了避免该问题,需要从 DataEvents
回调中移除 pdfViewer.collaborate
的调用,并将其放置到单击事件回调中。
var $button = jQuery('#create-square-button');
$button.on('click', function() {
var doc = pdfViewer.getCurrentPDFDoc();
doc.getPageByIndex(0).then(function(page) {
page.addAnnot({
color: 0xff0000,
rect: { left: 300, right: 400, top: 300, bottom: 200 },
flags: 4,
type: 'square'
}).then(function(annots) {
return doc.exportAnnotsToJSON(annots);
}).then(function(annotsJSONArray) {
pdfViewer.collaborate(PDFViewCtrl.collab.COLLABORATION_ACTION.CREATE_ANNOT, {
annots: annotsJSONArray
})
});
});
});
var $button = jQuery('#create-line-button');
$button.on('click', function() {
var doc = pdfViewer.getCurrentPDFDoc();
doc.getPageByIndex(0).then(function(page) {
page.addAnnot({
type: 'line',
startStyle: 0,
endStyle: PDF.constant.Ending_Style.Square,
startPoint: {x: 0, y: 0},
endPoint: {x: 100, y: 100},
rect: {
left: 0,
right: 100,
top: 0,
bottom: 100
}
}).then(function(annots) {
return doc.exportAnnotsToJSON(annots);
}).then(function(annotsJSONArray) {
pdfViewer.collaborate(PDFViewCtrl.collab.COLLABORATION_ACTION.CREATE_ANNOT, {
annots: annotsJSONArray
})
});
});
});