Skip to content

Undo/Redo

简介

福昕 PDF SDK Web 版提供了一个名为 "undo-redo" 的插件,它可以为 PDF 文档添加撤销和重做功能。用户可以通过 Ctrl+ZCtrl+Y 组合键来撤销和重做以下操作:

  • 添加注释
  • 删除注释
  • 修改注释
  • 等等

此外,该插件还提供了编程接口,允许开发者在自定义应用中实现撤销和重做功能。

加载插件

请参考 Addons 简介 章节中的方法。插件加载后, undo-redo 功能便会自动生效。用户可以通过 Ctrl+ZCtrl+Y (Mac 中为 Cmd+ZCmd+Y)来撤销和重做上一步操作。

编程接口

除了提供快捷键之外,undo-redo 插件还提供了一系列编程接口帮助开发者实现自定义功能。在调用接口之前,需要先获取 undo-redo 插件的对象实例:

javascript
async function obtainAddonInstanceExample() {
    const undoRedoAddon = await pdfui.getAddonInstance("UndoRedoAddon");
    if (undoRedoAddon) {
        // Here you can begin to use the methods of undoRedoAddon object.
    } else {
        console.error("UndoRedo Addon instance not found.");
    }
}

关于 UndoRedoAddon 详细的接口描述,可以参考 API Reference

获取到 UndoRedoAddon 实例后,接下来开始使用它。

撤销操作

undoRedoAddon.undo() 接口用于撤销操作,它可以撤销用户的最后一次操作。示例如下:

javascript
async function undoExample() {
    const undoRedoAddon = await pdfui.getAddonInstance("UndoRedoAddon");
    if (undoRedoAddon) {
        undoRedoAddon.undo();
    } else {
        console.error("UndoRedo Addon instance not found.");
    }
}

重做操作

undoRedoAddon.redo() 接口用于重做操作,它可以重新执行最后一次被撤销的用户操作。示例如下:

javascript
async function redoExample() {
    const undoRedoAddon = await pdfui.getAddonInstance("UndoRedoAddon");
    if (undoRedoAddon) {
        undoRedoAddon.redo();
    } else {
        console.error("UndoRedo Addon instance not found.");
    }
}

撤销所有操作

undoRedoAddon.undoAll() 接口用于撤销所有操作,它可以撤销用户所有的操作,将文档还原到最初状态。示例如下:

javascript
async function undoAllExample() {
    const undoRedoAddon = await pdfui.getAddonInstance("UndoRedoAddon");
    if (undoRedoAddon) {
        undoRedoAddon.undoAll();
    } else {
        console.error("UndoRedo Addon instance not found.");
    }
}

虽然所有操作被撤销,但是也依然可以一步一步地重做。

记录操作

UndoRedoAddon 还提供了一个 invoke 方法,可以通过该方法传递回调函数。该函数接受一个 PDFDoc 对象,该对象是一个被包装过的对象。相对于未包装过的 PDFDoc ,其不同之处在于可以记录操作,这些被记录的操作可以被撤销和重做。

下面是一个简单的示例,在回调函数中记录了创建注释和修改注释的操作。这些操作被记录后,可以通过 undo/redo 接口来撤销和重做:

javascript
function wait() {
    // 这个函数的作用是让下面的每个步骤执行完后停顿一定时间,方便查看效果。
    return new Promise((resolve) => setTimeout(resolve, 2000));
}

async function invokeExample() {
    const undoRedoAddon = await pdfui.getAddonInstance("UndoRedoAddon");
    if (undoRedoAddon) {
        await undoRedoAddon.invoke(async (pdfDoc) => {
            const pdfPage = await pdfDoc.getPageByIndex(0);
            const [square, popup] = await pdfPage.addAnnot({
                type: "square",
                rect: {
                    left: 0,
                    right: 100,
                    bottom: 500,
                    top: 550,
                },
                color: 0xff0000, // 初始化外边框颜色为:红色
            });
            await wait();
            // 创建完成后,将外边框颜色设置为紫色
            await square.setBorderColor(0xff00ff);
        });

        await wait();

        // 撤销后,颜色变回红色
        await undoRedoAddon.undo();

        await wait();

        // 重做后,颜色变为紫色
        await undoRedoAddon.redo();

        await wait();

        // 撤销所有,square Annotation 将被删除
        await undoRedoAddon.undoAll();
    } else {
        console.error("UndoRedo Addon instance not found.");
    }
}

支持 Undo/Redo 的 API 列表

下面列举了 SDK 当前支持撤销和重做操作的 API。

支持的对象获取接口

这里列举了一系列接口,当在 UIXAddon.invoke 回调函数中被调用时,会返回一个被包装过的对象。开发者可以调用这个被包装过的对象的方法来记录操作:

  1. PDFDoc 接口

    • PDFDoc.getPageByIndex(index): 通过索引获取文档中的页面。
    • PDFDoc.getPageById(id): 通过页面的唯一标识符获取页面。
    • PDFDoc.getAnnots(): 获取文档中的所有注释。
  2. PDFPage 接口

    • PDFPage.getAnnots(): 获取页面上的所有注释。
    • PDFPage.getAnnotsByObjectNumArray(objectNums): 通过对象编号数组获取页面上的注释。
    • PDFPage.getAnnotsByIdArray(annotIds): 通过注释标识符数组获取页面上的注释。
    • PDFPage.getMarkupAnnots(): 获取页面上的标记注释。
    • PDFPage.getAnnotTree(): 获取页面上注释的树状结构。

示例:

javascript
async function getAnnotsExample() {
    const undoRedoAddon = await pdfui.getAddonInstance("UndoRedoAddon");
    if (undoRedoAddon) {
        await undoRedoAddon.invoke(async (pdfDoc) => {
            const pdfPage = await pdfDoc.getPageByIndex(0);
            const [square] = await pdfPage.getAnnotsByObjectNumArray([12002]);
            square.setBorderColor(0xFF0000);
        });
        await undoRedoAddon.undo();
    } else {
        console.error("UndoRedo Addon instance not found.");
    }
}

支持的操作接口

这些接口被调用后,其操作将会被自动记录,记录后的操作可以被撤销和重做。要注意的是,这些接口必须在上一段中列举的 对象获取接口 返回的对象上调用。

  1. PDFDoc 接口
    • PDFDoc.addAnnot
  2. PDFPage 接口
    • PDFPage.addAnnot
    • PDFPage.removeAnnotById
    • PDFPage.removeAnnotByObjectNumber
  3. Annot 接口 (所有注释类的超类):
    • Annot.setContent
    • Annot.setRect
    • Annot.setBorderColor
    • Annot.setBorderInfo
    • Annot.setFlags
  4. Markup 接口 (所有 Markup 注释的超类, 包括:FreeText (callout, textbox, typewriter), ink, line, note, polygon, polyline, redact, sound, square, stamp and TextMarkup (highlight, squiggly, strikeout, underline)):
    • Markup.setOpacity
    • Markup.setSubject
    • Markup.setTitle
    • Markup.addReply
    • Markup.addReviewState
    • Markup.addMarkedState
    • Markup.setFillColor
  5. 特定的注释类型:
    • Circle
      • Circle.setMeasureRatio
      • Circle.setMeasureUnit
      • Circle.setMeasureConversionFactor
      • Circle.enableCaption
      • Circle.setCaptionColor
    • Line
      • Line.setMeasureRatio
      • Line.setMeasureUnit
      • Line.enableCaption
      • Line.setCaptionColor
      • Line.setEndPoint
      • Line.setStartPoint
      • Line.setEndingStyle
      • Line.setStyleFillColor
      • Line.setLeaderLineExtend
      • Line.setLeaderLineOffset
      • Line.setLeaderLineLength
      • Line.setCaptionOffset
    • Polygon
      • Polygon.enableCaption
      • Polygon.setCaptionColor
      • Polygon.updateVertexes
      • Polygon.setVertexes
    • Polyline
      • Polyline.setMeasureRatio
      • Polyline.enableCaption
      • Polyline.setCaptionColor
      • Polyline.setEndingStyle
      • Polyline.setStyleFillColor
      • Polyline.updateVertexes
      • Polyline.setVertexes
    • Square
      • Square.setMeasureRatio
      • Square.setMeasureUnit
      • Square.setMeasureConversionFactor
    • FreeText(typewriter, textbox, callout)
      • FreeText.setAlignment
      • FreeText.setInnerRect
      • FreeText.setCalloutLinePoints
      • FreeText.setCalloutLineEndingStyle
      • FreeText.setDefaultAppearance
      • FreeText.setRotation
    • Screen
      • Screen.setRotation
    • Stamp
      • Stamp.setRotation
    • Redact
      • Redact.setDefaultAppearance
      • Redact.setOverlayText
      • Redact.removeOvelayText
      • Redact.setOverlayTextAlignment
      • Redact.setRepeat
      • Redact.setAutoFontSize
      • Redact.setRedactApplyFillColor
    • Ink
      • Ink.setInkList
    • Link
      • Link.setHighlightingMode
      • Link.setAction
    • FileAttachment
      • FileAttachment.setIconName
    • Note
      • Note.setIconName