Skip to content

缩略图

本章节主要介绍了缩略图面板的 UI 结构、布局、标签等内容。 其中涉及到 fragment 的相关操作可以查阅 UI fragments 小节。如果您想了解更多组件相关 API,可查阅 API Reference 文档。

缩略图面板组件结构说明

在开始实现自定义缩略图 UI 之前, 我们需要先了解这些组件的结构:

  1. thumbnail Addon
  2. 缩略图面板
  3. 缩略图列表

thumbnail Addon

在开始使用缩略图组件前,请先确保 thumbnail Add 已经正确加载 (可参考 这里)。关于如何加载 Addon 的相关文档,请参考 这里

缩略图面板

在内置的布局模板中,<thumbnail-sidebar-panel></thumbnail-sidebar-panel> 是左侧边栏缩略图面板,它实际上相当于下面的模板:

html

<thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
    <thumbnail:toolbar></thumbnail:toolbar>
    <thumbnail:complete-thumbnail-list></thumbnail:complete-thumbnail-list>
</thumbnail:sidebar-panel>

它包含 <thumbnail:toolbar><thumbnail:complete-thumbnail-list> 两个子组件。 如果您想要更改结构,可以参考以下模板:

html
<thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
    <thumbnail:complete-thumbnail-list></thumbnail:complete-thumbnail-list>
    <thumbnail:toolbar></thumbnail:toolbar>
</thumbnail:sidebar-panel>

接下来通过 fragments 配置替换内置的 sidebar-thumbnail-panel

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:complete-thumbnail-list></thumbnail:complete-thumbnail-list>
                            <thumbnail:toolbar></thumbnail:toolbar>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
    "iframeOptions": {
        "style": "height: 500px"
    }
}

缩略图列表

<thumbnail:complete-thumbnail-list> 是一个包含了完整缩略图列表功能的组件,如下所示:

html
<thumbnail:thumbnail-list
    @thumbnail:centered
    @thumbnail:rearrange-pages
    @thumbnail:drop-to-merge-doc
    @aria:label="thumbnail:title"
>
    <thumbnail:thumbnail-item
        @foreach="thumbnail in thumbnail_list.thumbnails track by id"
        @setter.thumbnail_id="thumbnail.id"
        @lazy-content="visible"
    >
        <div class="fv__ui-thumbnail-viewer-container">
            <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
        </div>
        <div class="fv__ui-thumbnail-item-label">@{thumbnail.pageIndex+1}</div>
    </thumbnail:thumbnail-item>
</thumbnail:thumbnail-list>

其中涉及的各个结构说明如下:

所在节点结构类型是否必须说明
<thumbnail:thumbnail-list>@thumbnail:centered指令用户拖拽侧边栏面板调整面板宽度时,能够控制缩略图列表项正常换行并居中显示
<thumbnail:thumbnail-list>@thumbnail:rearrange-pages指令用于支持拖拽缩略图以调整 PDF 页面顺序
<thumbnail:thumbnail-list>@thumbnail:drop-to-merge-doc指令用于实现将从外部拖拽到缩略图列表的 PDF 文档插入到指定的位置的功能
<thumbnail:thumbnail-list>@aria:label="thumbnail:title"指令无障碍属性
<thumbnail:thumbnail-item>@foreach="thumbnail in thumbnail_list.thumbnails track by id"指令这是用于创建缩略图列表的指令,不可修改
<thumbnail:thumbnail-item>@setter.thumbnail_id="thumbnail.id"指令缩略图项目必须要的一个指令,用于设置缩略图 id
<thumbnail:thumbnail-item>@lazy-content="active"指令用于提升加载缩略图性能
div.fv__ui-thumbnail-viewer-container-HTML Elementthumbnail-viewer 容器,不需要做任何调整
<thumbnail:thumbnail-viewer>@thumbnail:visible-rect-control指令用于标记和控制 PDF 可见区域
div.fv__ui-thumbnail-item-label-HTML Element这是一个用于显示当前页缩略信息的容器,我们可以通过修改它来显示更多信息

当您需要自定义缩略图列表时,您需要将 <thumbnail:complete-thumbnail-list> 替换为上述模板,如下所示:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:toolbar></thumbnail:toolbar>
                            <thumbnail:thumbnail-list
                                @thumbnail:centered
                                @thumbnail:rearrange-pages
                                @thumbnail:drop-to-merge-doc
                                @aria:label="thumbnail:title"
                            >
                                <thumbnail:thumbnail-item
                                    @foreach="thumbnail in thumbnail_list.thumbnails track by id"
                                    @setter.thumbnail_id="thumbnail.id"
                                    @lazy-content="visible"
                                >
                                    <div class="fv__ui-thumbnail-viewer-container">
                                        <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
                                    </div>
                                    <div class="fv__ui-thumbnail-item-label">@{thumbnail.pageIndex+1}</div>
                                </thumbnail:thumbnail-item>
                            </thumbnail:thumbnail-list>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
    "iframeOptions": {
        "style": "height: 500px"
    }
}

我们运行上面示例,效果和内置的实现效果相同。

开始自定义缩略图

自定义缩略图包括:

自定义缩略图项目信息

<div class="fv__ui-thumbnail-item-label">@{thumbnail.pageIndex+1}</div> 改为 <div class="fv__ui-thumbnail-item-label">Page: @{thumbnail.pageIndex+1}</div>, 效果如下:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:toolbar></thumbnail:toolbar>
                            <thumbnail:thumbnail-list
                                @thumbnail:centered
                                @thumbnail:rearrange-pages
                                @thumbnail:drop-to-merge-doc
                                @aria:label="thumbnail:title"
                            >
                                <thumbnail:thumbnail-item
                                    @foreach="thumbnail in thumbnail_list.thumbnails track by id"
                                    @setter.thumbnail_id="thumbnail.id"
                                    @lazy-content="visible"
                                >
                                    <div class="fv__ui-thumbnail-viewer-container">
                                        <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
                                    </div>
                                    <div class="fv__ui-thumbnail-item-label">Page: @{thumbnail.pageIndex+1}</div>
                                </thumbnail:thumbnail-item>
                            </thumbnail:thumbnail-list>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
    "iframeOptions": {
        "style": "height: 500px"
    }
}

您还可以调整缩略图结构并插入更多组件:

html
<script>
    const libPath = window.top.location.origin + '/lib';
    const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    const pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'sidebar-thumbnail-panel',
                    action: FRAGMENT_ACTION.REPLACE,
                    template: `
                        <thumbnail:sidebar-panel name="sidebar-thumbnail-panel" @lazy-content="active">
                            <thumbnail:toolbar></thumbnail:toolbar>
                            <thumbnail:thumbnail-list
                                @thumbnail:centered
                                @thumbnail:rearrange-pages
                                @thumbnail:drop-to-merge-doc
                                @aria:label="thumbnail:title"
                            >
                                <thumbnail:thumbnail-item
                                    @foreach="thumbnail in thumbnail_list.thumbnails track by id"
                                    @setter.thumbnail_id="thumbnail.id"
                                    @lazy-content="visible"
                                >
                                    <div class="my-thumbnail-item-toolbox">
                                        <button @controller="thumbnail:DeletePageController">delete</button>
                                        <button @controller="thumbnail:RotateRightController">rotate right</button>
                                        <button @controller="thumbnail:RotateLeftController">rotate left</button>
                                    </div>
                                    <div class="fv__ui-thumbnail-viewer-container">
                                        <thumbnail:thumbnail-viewer @setter.thumbnail="thumbnail" @thumbnail:visible-rect-control></thumbnail:thumbnail-viewer>
                                    </div>
                                </thumbnail:thumbnail-item>
                            </thumbnail:thumbnail-list>
                        </thumbnail:sidebar-panel>
                    `
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    .my-thumbnail-item-toolbox {
        display: flex;
        padding: 0.2em 0;
        flex-direction: row;
    }
    .my-thumbnail-item-toolbox button{
        height: 2em;
        line-height: 1;
        font-size: 12px;
    }
</style>
json
{
    "iframeOptions": {
        "style": "height: 500px"
    }
}

自定义缩略图右键菜单

以下是缩略图右键菜单的模板:

html
<contextmenu name="fv--thumbnail-contextmenu" @thumbnail:permission>
    <contextmenu-item feature="rotate" name="contextmenu-item-thumbnail-rotate-left" @controller="thumbnail:RotateLeftController">thumbnail:contextmenu.rotateLeft</contextmenu-item>
    <contextmenu-item feature="rotate" name="contextmenu-item-thumbnail-rotate-right" @controller="thumbnail:RotateRightController">thumbnail:contextmenu.rotateRight</contextmenu-item>
    <contextmenu-separator></contextmenu-separator>
    <contextmenu-item feature="insert" name="contextmenu-item-thumbnail-add-blank-page" @controller="thumbnail:InsertBlankPageController">thumbnail:contextmenu.addBlankPage</contextmenu-item>
    <contextmenu-separator></contextmenu-separator>
    <thumbnail:delete-page-contextmenu-item name="contextmenu-item-thumbnail-delete"></thumbnail:delete-page-contextmenu-item>
</contextmenu>

我们可以通过修改 fragments 配置来删除或添加菜单项:

html
<script>
    var libPath = window.top.location.origin + '/lib';
    var FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
    var customModule = UIExtension.modular.module('custom', []);

    customModule.registerController(UIExtension.Controller.extend({
        mounted: function() {
            pdfui.callAddonAPI('Thumbnail','onSelectThumbnail', [function(currentSelectedPageIndexes) {
                console.log(currentSelectedPageIndexes);
            }]).then(removeListener => {
                this.addDestroyHook(removeListener);
            })
        }
    }, {
        getName: function() {
            return 'CustomThumbnailItemOperationController';
        }
    }));
    
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: UIExtension.appearances.adaptive.extend({
            getDefaultFragments() {
                return [{
                    target: 'contextmenu-item-thumbnail-delete',
                    action: FRAGMENT_ACTION.REMOVE
                }, {
                    target: 'fv--thumbnail-contextmenu',
                    action: FRAGMENT_ACTION.APPEND,
                    template:`<contextmenu-item @controller="thumbnail:DeletePageController">Custom delete page menu</contextmenu-item>`
                }, {
                    target: 'fv--thumbnail-contextmenu',
                    action: FRAGMENT_ACTION.APPEND,
                    template: `<contextmenu-item @controller="custom:CustomThumbnailItemOperationController">Custom Action</contextmenu-item>`
                }]
            }
        }),
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
    "iframeOptions": {
        "style": "height: 500px"
    }
}