Анотації
Додайте підтримку анотацій у переглядач
Анотації в Doconut працюють у двох напрямках: користувачі малюють їх у віджеті браузера, а сервер зберігає їх по сторінках, або ваш код створює їх програмно і завантажує у відкриту сесію. У будь-якому випадку вони відображаються на сторінках і можуть бути вбудовані у PDF/PNG експорти.
Підтримка анотацій контролюється можливістю ліцензії Annotation (надається автоматично при активній тимчасовій ліцензії).
Увімкнути інтерфейс анотацій
Annotation — це модуль Viewer, а не окрема панель інструментів. Повна сторінка повинна включати ресурси Viewer, панель інструментів Viewer, монтування Viewer та ініціалізований objViewer; після цього стрічка Annotation монтується і підключається до того ж екземпляра.
Випускайте пакети анотацій разом з пакетами переглядача — вони підлягають ліцензійному контролю, тому теги з’являються лише коли можливість доступна:
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
IncludeViewerCss = true,
IncludeAnnotationCss = true // jquery-ui.min.css + annotationBar.css
}))
@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeViewerScripts = true,
IncludeAnnotationScripts = true, // jquery-ui, raphael.js, annotation.js
IncludeAnnotationBar = true // the embedded annotation ribbon
}))Залиште повну композицію Viewer видимою у розмітці:
<nav id="toolbar" aria-label="Document viewer controls">
<!-- Елементи управління переглядачем, включаючи кнопку, що відкриває Annotation -->
</nav>
<div id="annBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>Пакет Annotation генерує DOM стрічки всередині annBarMount; вам не потрібно копіювати його кнопки чи розмітку діалогових вікон. Спочатку ініціалізуйте docViewer, а потім створюйте стрічку лише коли сервер підтвердить, що Annotation ліцензовано:
<script>
let annBar = null;
let currentToken = '';
const objViewer = $('#div_ctlDoc').docViewer({
BasePath: 'doconut',
ResPath: 'doconut-res/images',
onAnnLoaded: () => annBar?.handleAnnLoaded(),
onAnnSaved: () => annBar?.handleAnnSaved(),
onAnnSaveError: () => annBar?.handleAnnSaveError(),
onAnnClosed: () => annBar?.handleAnnClosed(),
onError: (message) => console.error('Viewer error:', message)
});
@if (Viewer.IsAnnotationEnabled)
{
<text>
annBar = $('#annBarMount').doconutAnnotationBar({
docId: 'ctlDoc',
getRequestParams: () => ({ token: currentToken }),
onStatus: (message) => console.log(message),
onToast: (message, type) => console.log(type, message),
onLayout: () => requestAnimationFrame(() => objViewer.Refit())
});
annBar.attach(objViewer);
</text>
}
</script>Збереження зі стрічки надсилає дані через проміжне ПЗ (AnnSave), яке зберігає їх у сесії документа по сторінках. Завантаження (AnnLoad) відбувається автоматично, коли сторінка з анотаціями відображається. Чотири зворотні виклики onAnn* синхронізують стрічку зі життєвим циклом переглядача.
Відкривайте та закривайте її з будь‑якої панелі інструментів Viewer, що належить хосту:
annBar.open();
annBar.close();Публічний API стрічки:
| Метод | Призначення |
|---|---|
attach(objViewer) | Підключити стрічку до ініціалізованого переглядача; необхідно один раз |
open() / close() | Відкрити або закрити режим редагування анотацій |
reset() | Повернути стрічку у закрите, не‑редагувальне стан |
isOpen() / annotating() | Прочитати стан стрічки / стан редагування анотацій у переглядачі |
reopenEditable() | Перезавантажити анотації поточної сторінки як редаговані об’єкти |
updateActionState() | Оновити доступність елементів керування збереженням/видаленням після змін у хості |
headerSlot() | Отримати необов’язковий слот розширення заголовка для елементів керування, що належать хосту |
onStatus, onToast, onLayout, onEditStart та onEditEnd — це необов’язкові зворотні виклики хоста. Об’єкт endpoints може додатково надавати exportPdf, exportPng, imageUpload і imageList; елементи без налаштованого кінцевого пункту залишаються прихованими. Для послідовності запуску комбінованих Viewer, Search та Annotation дивіться Швидкий старт.
Пакет анотацій додає інструменти авторингу в браузері, проте дані все ще належать серверній сесії документа, ідентифікованій токеном. Перезапуск джерела створює нову сесію; збережіть XML або закодований конверт анотацій у вашому застосунку, якщо анотації мають пережити завершення сесії.
Створення анотацій у C#
Отримайте менеджер, прив’язаний до відкритої сесії, додайте анотації та завантажте їх (з using Doconut.Annotations; для типів і using System.Drawing; для Rectangle/Color):
app.MapPost("/api/annotations/load-sample", (string token, Viewer viewer) =>
{
// Прив’язано до розмірів сторінки відкритої сесії
var manager = viewer.GetAnnotationManager(token);
var pageCount = viewer.GetPageCount(token);
// Один штамп на сторінку
for (int page = 1; page <= pageCount; page++)
{
manager.Add(new StampAnnotation(page, new Rectangle(30, 20, 240, 90),
$"PAGE {page}", 28, 4, Color.Maroon)
{
Opacity = 60,
Rotate = -8
});
}
manager.Add(new NoteAnnotation(1, new Rectangle(420, 150, 220, 120),
"Loaded from C# code.", Color.FromArgb(255, 255, 255, 170), 14));
// Завантажити у сесію — віджет отримує їх через AnnLoad і
// рендерер вбудовує їх у експорт зображень/PDF.
viewer.LoadAnnotationData(token, manager);
return Results.Ok();
});Типи анотацій
Усі типи розташовані в Doconut.Annotations і успадковуються від BaseAnnotation (номер сторінки + обмежувальний Rectangle):
| Тип | Примітки |
|---|---|
StampAnnotation | Текстовий штамп з розміром шрифту, рамкою, кольором; підтримує Opacity, Rotate |
NoteAnnotation | Нотатка‑стикер з текстом, кольором фону, розміром шрифту, TitleColor |
RectangleAnnotation | Колір рамки та заповнення, Title/ShowTitle |
CircleAnnotation | Рамка + заповнення, ShowBorder |
EllipseAnnotation | Рамка + заповнення, ShowBorder |
TriangleAnnotation | Колір рамки, BackColor, ShowBorder |
LineAnnotation | Пряма лінія з шириною та кольором |
ArrowAnnotation | Лінія зі стрілкою; налаштовуваний Direction (тип ArrowDirection, напрямки компаса, за замовчуванням E) |
FreehandAnnotation | Вільний штрих з закодованих точок FreehandData |
ImageAnnotation | Зображення за URL. Відносний URL розв’язується відносно хоста запиту, коли анотація додається (завантаження зображення відбувається лише під час «запікання») — воно має бути доступним з сервера (наприклад, файл у wwwroot, який обслуговується UseStaticFiles) |
API AnnotationManager
| Член | Призначення |
|---|---|
Add(BaseAnnotation) | Додати анотацію в чергу |
GetAnnotations() / GetAnnotations(int page) | Переглянути, що містить менеджер |
ClearAnnotations() / ClearAnnotations(int page) | Видалити всі / по сторінці |
GetAnnotationData() / GetAnnotationData(int page) | Кодований рядок даних анотації — Base64‑обгортка (те, що споживає віджет) |
GetAnnotationXml() | XML‑форма |
Viewer відтворює операції завантаження/читання щодо сесії: LoadAnnotationData(token, manager) або LoadAnnotationData(token, encodedData) (Base64‑обгортка з GetAnnotationData()), LoadAnnotationXML(token, xml), GetAnnotationXML(token).
Експорт з вбудованими анотаціями
// PDF усіх сторінок з анотаціями, накладеними на них
app.MapGet("/api/annotations/export-pdf", async (string token, Viewer viewer) =>
{
byte[] pdf = await viewer.ExportAnnotationsToPdfAsync(token, zoom: 100);
return Results.File(pdf, "application/pdf", "export.pdf");
});
// Або ZIP з PNG‑файлами по кожній сторінці
app.MapGet("/api/annotations/export-png-zip", async (string token, Viewer viewer) =>
{
byte[] zip = await viewer.ExportAnnotationsToPngZipAsync(token, zoom: 100);
return Results.File(zip, "application/zip", "annotations-png.zip");
});Експорти використовують той самий механізм «запікання», що й відображення на екрані, тому те, що бачать користувачі, саме так і міститься у файлі.
Робочий процес збереження
- Відкрийте документ і отримайте його токен.
- Завантажте раніше збережений XML або закодовані дані у цей токен.
- Дайте віджету прочитати та редагувати анотації сесії.
- Отримайте XML за допомогою
GetAnnotationXML(token), коли ваш застосунок вирішить зберегти дані. - Експортуйте PDF/PNG, коли потрібен сплющений результат.
- Закрийте сесію документа.
Не використовуйте непрозорий токен переглядача як постійний ідентифікатор анотації. Пов’язуйте збережені дані анотації зі своїми ідентифікаторами документу та його версії.
Примітки щодо безпеки та рендерингу
- Запити анотацій використовують ту ж безпеку сесії/токену, що й запити сторінок.
- Відносна
ImageAnnotationURL-адреса розв’язується з хоста запиту і повинна залишатися доступною для сервера під час обробки. - Перевіряйте та контролюйте будь-яку URL-адресу зображення, надану користувачем, щоб уникнути підробки запитів на стороні сервера.
- Експорти застосовують ті ж рішення щодо ліцензії/власного водяного знака, що й рендеринг сторінок на екрані.
- Великі вільноручні дані та експорти високої роздільної здатності збільшують використання пам’яті; тестуйте реалістичні документи та значення масштабу.
Усунення неполадок
| Симптом | Перевірка |
|---|---|
| Рубрика анотацій відсутня | Annotation можливість та чотири прапорці CSS/script анотації |
| Зворотний виклик збереження повідомляє про помилку | Термін дії токену/сесії закінчився та middleware BasePath |
| Анотації C# не відображаються | Нумерація сторінок починається з одиниці, і дані були завантажені в активний токен |
| Зображення анотації відображається на екрані, але не в експорті | Сервер може досягти URL-адреси зображення під час обробки |
| Повторно відкритий документ не містить анотацій | Зберігайте XML/дані поза сесією переглядача, потім завантажте їх у новий токен |
Чи була ця сторінка корисною?