概要: WebViewer では、ブランディングや UI の変更から他のシステムとのシームレスな統合まで、UI を正確な仕様に合わせて簡単にカスタマイズできます。最新のアップデートにより UI の調整が簡素化され、パーソナライズされた洗練されたユーザー エクスペリエンスが保証されるため、ソース コードをフォークする必要はありません。
はじめに
Apryse WebViewer は、PDF やその他のドキュメント タイプの表示、注釈付け、操作のための幅広い機能を提供する優れたツールです。これには、デジタル署名、フォーム入力、編集のサポートが含まれます。
WebViewer 10.6 までにおいても、ブランディング、UI の変更、他のシステムとの統合などの特定の要件を満たすように WebViewer UI をカスタマイズすることが既に可能でした。たとえば、要素の表示/非表示、タイトルやアイコンの変更、表示言語の変更などが簡単にできました。さらに大幅な変更を行うには、オープンソースの WebViewer UI をフォークして、開発の手間はかかりますが、ほぼ無制限のカスタマイズ オプションを提供することも可能でした。
10.7 では UI を変更する機能が大幅に簡素化されたため、多くのユーザーは、必要な外観と操作性を実現するためにソース コードをフォークする必要がなくなりました。
この記事では、 UI に新しいボタンを追加し、カスタム機能を実装するために必要な手順について説明します。
達成しようとしていること
例として、表示中の PDF の現在のページのテキストを表示できるボタンをヘッダーに追加します。初期ドキュメントが読み込まれますが (WebViewer Showcase のファイルに基づく)、ファイルを選択する機能も追加されます。
これは単純な例ですが、この記事で説明するテクニックは、次のようなボタンを追加する基礎として使用できます。
- PDF からデジタル署名の画像を検索、抽出、表示
- ドキュメントからテキストを検索して銀行の詳細を表示
- OCG (オプション コンテンツ グループ) を含む PDF 内の特定のレイヤーを表示
サポートする必要があるニッチなビジネス要件に合わせてボタンを作成することもできます。
この例のコードは、Vite を使用して作成された React TypeScript プロジェクトのものですが、原則は他のフレームワークでも同じです。この例のコードは、本番環境で使用できるように意図されたものではなく、必要な手順の概要を示すことを目的としています。
モジュラー UI の設定
デフォルトでは、WebViewer 10.7 では従来の UI が使用されます。ただし、新しいモジュラー UI への切り替えは簡単です。WebViewer コンストラクターで ui:’beta’ を指定するだけです。
useEffect(() => {
WebViewer({
path: 'lib',
initialDoc: 'files/WebviewerDemoDoc.pdf',
ui: 'beta' // enable Modular UI
}, viewerDiv.current as HTMLDivElement).then((instance) => {
一見すると、新しい UI を使用していることに気付かないかもしれません。しかし、微妙にリフレッシュされているため、違いがあります。
ただし、注釈などのツール リボン グループの項目をクリックすると、変更がすぐにわかります。個々のツールはすべて、新しく新鮮な外観になっています。
ビルトイン ヘッダー メニューの置き換え
この例では多くの機能は必要ないので、「通常の」トップ ヘッダー メニューを、topHeader というカスタム メニューに置き換えてみましょう。何ができるかの例として、ヘッダー メニューが WebViewer の上部ではなく左側にあるように指定します。
デフォルトのメイン メニュー (バーガー メニュー) をヘッダーに追加し、メソッドUI.enableFeatures を使用して、 FilePicker でローカルにファイルを選択する機能を追加します。これは、以前のバージョンの WebViewer で UI をカスタマイズするのと同じ方法です。
useEffect(() => {
WebViewer({
path: 'lib',
initialDoc: 'files/WebviewerDemoDoc.pdf',
ui: 'beta' // enable Modular UI
}, viewerDiv.current as HTMLDivElement).then((instance) => {
const { UI, Core } = instance;
const { documentViewer } = instance.Core;
UI.enableFeatures([UI.Feature.FilePicker]);
// @ts-ignore comment.
const mainMenu = new UI.Components.MainMenu();
// @ts-ignore comment.
const topHeader = new instance.UI.Components.ModularHeader({
dataElement: 'default-top-header',
placement: 'left',
grow: 0,
gap: 12,
position: 'start',
setJustifyContent:('center'),
stroke: true,
dimension: {
paddingTop: 8,
paddingBottom: 8,
borderWidth: 1
},
style: {},
items: [
mainMenu,
// you could add many other items if you wish
]
});
// @ts-ignore comment.
instance.UI.setModularHeaders([topHeader]);
}
);
}, [])
コードの変更を保存すると、UI が更新され、ドキュメントの左側に新しいメニュー オプションが表示されます。
UI の見た目はすでに大きく変わり、不要なオプションは削除しました。次に、PDF の現在選択されているページにあるテキストを表示できるようにカスタム ボタンを追加しましょう。
これらは段階的に進めていきます。まず、テキストを取得する方法、カスタム パネルにテキストを表示する方法、テキストを UI に追加してカスタムのステートフル ボタンから制御する方法について説明します。
現在のページのテキストを取得
現在のページのテキストは、次のコードを使用して抽出できます。
const getTextOnPage = async () => {
const doc = documentViewer.getDocument();
if (doc) {
const currentPageNum = documentViewer.getCurrentPage();
const info = doc.getPageInfo(currentPageNum);
const rect = new Core.Math.Rect(0, 0, info.width, info.height)
const text = await doc.getTextByPageAndRect(currentPageNum, rect);
return text;
}
//if no document is loaded then return an empty string
return "";
}
この動作は、documentViewer から現在のページを取得し、 doc からそのページのサイズを取得して、ドキュメントのその部分からテキストを抽出します。 getTextByPageAndRect は promise を返すため、 await を使用する必要があることに注意してください。
返される値は、ユーザーに表示する内容です (ドキュメントが利用できない場合は何も表示されません)。
ページ テキストの表示
ドキュメント テキストを使用してできることはたくさんあります。たとえば、何らかの関数に渡してデータを抽出したり、変更したりすることができます。ただし、この場合は、カスタム パネルに配置してユーザーに表示するだけです。
パネルの dataElement (ドキュメントごとに一意である必要があります) とその場所を指定する必要があります。オプションを示すために、これを right に設定します。また、React コンポーネントまたは HTML を直接返すレンダリング関数も必要です。
const createPanel = (txt: string) => {
//Add a new panel that contains the text
instance.UI.addPanel({
dataElement: 'customPanel',
location: 'right',
// @ts-ignore comment.
render: () => {
return <div className='custom-panel'>
{txt}
</div>
}
})
}
ここまでで、テキストを含むパネルを作成しましたが、まだ表示はされません。
カスタム パネルの表示
パネルを作成したにもかかわらず、UI はそれをどう処理すればよいかわかりません。パネルを表示させるのは簡単です。新しいパネルの名前を含むリストを指定して openElements を呼び出すだけです。
instance.UI.openElements(['customPanel']);
パネルの非表示
パネルの使用が終わったら、次のコードを呼び出すだけでパネルを閉じることができます。
instance.UI.closeElements(['customPanel']);
これによりパネルは閉じられますが、作成したパネルはそのまま残り、再度開くことができます。新しいページが最新になるたびに別のパネルが作成されると、リソース リークが発生する可能性があります。
この潜在的な問題にはいくつかの解決策があります。 1 つのオプションは、パネルを再利用して、選択したページが変更されると、そのページのテキストが抽出され、パネルを更新できるようにすることです。
ただし、このサンプル コードでは、パネルのリストを取得し、作成したパネルをフィルター処理して、 setPanels を使用して UI のパネルのリストを更新することで、パネルが閉じられたときにパネルを削除します。
const removePanelFromList = () => {
// @ts-ignore comment.
const panelsList = instance.UI.getPanels();
// @ts-ignore comment.
const newList = panelsList.filter(element => element._dataElement != 'customPanel')
// @ts-ignore comment.
instance.UI.setPanels(newList);
}
すべてをまとめる
これで、ページからテキストを取得し、パネルを作成し、パネルを表示または非表示にし、最後にパネルを削除するために必要なコードがすべて揃いました。最後に必要なのは、ユーザーがいつこれが発生するかを制御できるボタンを作成することです。この例では、StatefulButton を使用します(ただし、他のオプションを使用することもできます)。
このタイプのボタンは、名前が示すように、複数の状態を持つことができます。それぞれに、名前、タイトル、画像 (用意されている画像のいずれか、または選択してプロジェクトに追加したもの)、およびボタンの次の状態を指定する onClick イベント ハンドラーがあります。
const myStatefulButton = new instance.UI.Components.StatefulButton({
initialState: 'Show',
states: {
Show: {
// There are either prebuilt icons, or you can add one to the public folder and reference it
img: '/files/text-contents-icon.svg',
title: 'Show',
onClick: async (update: any) => {
update('Hide');
//Get and store the text for the current page
const txt = await getTextOnPage();
//Add a new panel that contains the text
createPanel(txt);
//Make the panel visible
instance.UI.openElements(['customPanel']);
},
},
Hide: {
img: '/files/close-text-contents-icon.svg',
title: 'Close',
onClick: (update: any) => {
update('Show');
instance.UI.closeElements(['customPanel']);
// Remove the created panel - alternatively you could write code to reuse the panel and update it.
removePanelFromList();
},
},
},
// Mount is a function that gets called when the button is mounted
// use it to set the initial state or do other setup
mount: () => { },
// Unmount is a function that gets called when the button is unmounted
// use it to clean up any resources
unmount: () => { },
});
この場合、状態は Show と Hide の 2 つだけです。
Show をクリックすると、すでに確認したコードがトリガーされます。現在のページのテキストが検索され、パネルに配置され、パネルが表示されます。重要なのは、update を使用して状態を Hide に設定することです。
一方、Hide をクリックすると、パネルは閉じられ、パネルのリストから削除されます (すでに説明したとおり)。その後、update を使用して状態を Show に戻します。
必要に応じて、 mount () と unmount ()を使用して初期化とクリーンアップのコードを設定することもできます。
最後に残っているのは、ヘッダー メニューに含める項目のリストに新しいボタンを追加することです。
items: [
mainMenu,
myStatefulButton,
// you could add many other items if you wish
]
これで完了です。任意のページのテキストを表示し、UI を更新するために使用できるサンプルができました。UI が開くと、最初の PDF が表示されます (ファイル ピッカーを使用して別の PDF を選択することもできます)。
任意のページまでスクロールし、カスタム ボタンをクリックすると、そのページのテキストがカスタム パネルに表示されます。
さいごに
この例はカスタム機能の単純な実装ですが、Apryse SDK 使用すると、作業するドキュメントを強力に制御できます。金融サービス、ヘルスケア、AEC、政府、法律、製薬、ライフサイエンスなど、どのような分野でも、Apryse では、業務の処理速度およびコストがかかる問題を解決するのに役立つツールを提供しています。
Apryse 製品の詳細は、弊社 Web サイトをご確認ください。
記事参照:
© 2024 Apryse
「Adding a Custom Button to the WebViewer UI with Modular Components」