Adnotacje
Dodaj obsługę adnotacji do przeglądarki
Adnotacje w Doconut działają w dwóch kierunkach: użytkownicy rysują je w widżecie przeglądarki, a serwer przechowuje je per strona, lub Twój kod tworzy je programowo i ładuje do otwartej sesji. W obu przypadkach są renderowane na stronach i mogą być wbudowane w eksporty PDF/PNG.
Obsługa adnotacji jest uzależniona od możliwości licencyjnej Annotation (przyznawana automatycznie w ramach aktywnej tymczasowej licencji).
Włącz interfejs UI adnotacji
Adnotacja jest modułem Viewer, a nie samodzielnym paskiem narzędzi. Pełna strona musi zawierać zasoby Viewer, pasek narzędzi Viewer, montaż Viewer oraz zainicjowany objViewer; wówczas wstążka Annotation jest montowana i dołączana do tej samej instancji.
Emituj pakiety adnotacji razem z pakietami przeglądarki — są one uzależnione od licencji, więc tagi pojawiają się tylko wtedy, gdy możliwość jest dostępna:
@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
}))Utrzymaj pełną kompozycję Viewer widoczną w znacznikach:
<nav id="toolbar" aria-label="Document viewer controls">
<!-- Viewer controls, including the button that opens Annotation -->
</nav>
<div id="annBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>Pakiet Annotation generuje DOM wstążki wewnątrz annBarMount; nie musisz kopiować jego przycisków ani znaczników dialogu. Zainicjuj najpierw docViewer, a następnie utwórz wstążkę tylko wtedy, gdy serwer potwierdzi, że Annotation jest licencjonowane:
<script>
let annBar = null;
let currentToken = '';
const objViewer = $('#div_ctlDoc').docViewer({
BasePath: '/',
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>Zapisywanie z wstążki wysyła dane przez warstwę pośrednią (AnnSave), która przechowuje je w sesji dokumentu per strona. Ładowanie (AnnLoad) odbywa się automatycznie, gdy strona z adnotacjami jest renderowana. Cztery wywołania zwrotne onAnn* utrzymują wstążkę zsynchronizowaną z cyklem życia przeglądarki.
Otwórz i zamknij ją z dowolnego paska narzędzi Viewer zarządzanego przez hosta:
annBar.open();
annBar.close();Publiczne API wstążki to:
| Metoda | Cel |
|---|---|
attach(objViewer) | Połącz wstążkę z zainicjowanym przeglądarką; wymagane jednorazowo |
open() / close() | Rozpocznij lub zakończ edycję adnotacji |
reset() | Przywróć wstążkę do zamkniętego, nieedytującego stanu |
isOpen() / annotating() | Odczytaj stan wstążki / stan edycji adnotacji w przeglądarce |
reopenEditable() | Przeładuj adnotacje bieżącej strony jako edytowalne obiekty |
updateActionState() | Odśwież dostępność kontrolek zapisu/usuwania po zmianach hosta |
headerSlot() | Pobierz opcjonalny slot rozszerzenia nagłówka dla kontrolek zarządzanych przez hosta |
onStatus, onToast, onLayout, onEditStart i onEditEnd są opcjonalnymi wywołaniami zwrotnymi hosta. Obiekt endpoints może dodatkowo udostępniać exportPdf, exportPng, imageUpload i imageList; kontrolki bez skonfigurowanego punktu końcowego pozostają ukryte. Aby zobaczyć sekwencję uruchamiania połączonych modułów Viewer, Search i Annotation, zobacz Szybki start.
Pakiet adnotacji dodaje narzędzia autorskie przeglądarki, ale dane nadal należą do sesji dokumentu po stronie serwera, identyfikowanej tokenem. Ponowne otwarcie źródła tworzy nową sesję; zachowaj XML lub zakodowaną powłokę adnotacji w swojej aplikacji, jeśli adnotacje muszą przetrwać poza okresem życia sesji.
Tworzenie adnotacji w C#
Uzyskaj menedżera powiązanego z otwartą sesją, dodaj adnotacje i załaduj je (z using Doconut.Annotations; dla typów oraz using System.Drawing; dla Rectangle/Color):
app.MapPost("/api/annotations/load-sample", (string token, Viewer viewer) =>
{
// Bound to the open session's page dimensions
var manager = viewer.GetAnnotationManager(token);
var pageCount = viewer.GetPageCount(token);
// One stamp per page
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));
// Load into the session — the widget fetches them via AnnLoad and the
// renderer burns them into image/PDF exports.
viewer.LoadAnnotationData(token, manager);
return Results.Ok();
});Typy adnotacji
Wszystkie typy znajdują się w Doconut.Annotations i dziedziczą po BaseAnnotation (numer strony + otaczający Rectangle):
| Type | Notes |
|---|---|
StampAnnotation | Znak tekstowy z rozmiarem czcionki, obramowaniem, kolorem; obsługuje Opacity, Rotate |
NoteAnnotation | Notatka samoprzylepna z tekstem, kolorem tła, rozmiarem czcionki, TitleColor |
RectangleAnnotation | Kolory obramowania i wypełnienia, Title/ShowTitle |
CircleAnnotation | Obramowanie + wypełnienie, ShowBorder |
EllipseAnnotation | Obramowanie + wypełnienie, ShowBorder |
TriangleAnnotation | Kolor obramowania, BackColor, ShowBorder |
LineAnnotation | Prosta linia o określonej szerokości i kolorze |
ArrowAnnotation | Linia z grotami; konfigurowalny Direction (typ ArrowDirection, punkty kompasu, domyślnie E) |
FreehandAnnotation | Swobodny odcinek z zakodowanych punktów FreehandData |
ImageAnnotation | Obraz z adresu URL. Względny URL jest rozwiązywany względem hosta żądania, gdy adnotacja jest dodawana (pobranie obrazu odbywa się dopiero przy wypalaniu) — musi być dostępny z serwera (np. plik w wwwroot serwowany przez UseStaticFiles) |
API AnnotationManagera
| Member | Purpose |
|---|---|
Add(BaseAnnotation) | Dodaj adnotację do kolejki |
GetAnnotations() / GetAnnotations(int page) | Sprawdź, co menedżer przechowuje |
ClearAnnotations() / ClearAnnotations(int page) | Usuń wszystkie / per strona |
GetAnnotationData() / GetAnnotationData(int page) | Zakodowany ciąg danych adnotacji — pakiet Base64 (co widget konsumuje) |
GetAnnotationXml() | Forma XML |
Viewer odzwierciedla operacje ładowania/odczytu w sesji: LoadAnnotationData(token, manager) lub LoadAnnotationData(token, encodedData) (pakiet Base64 z GetAnnotationData()), LoadAnnotationXML(token, xml), GetAnnotationXML(token).
Eksport z wypalonymi adnotacjami
// PDF of all pages with annotations rendered onto them
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");
});
// Or a ZIP of per-page PNGs
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");
});Eksporty używają tego samego mechanizmu wypalania co renderowanie na ekranie, więc to, co widzą użytkownicy, znajduje się w pliku.
Przebieg utrwalania
- Otwórz dokument i uzyskaj jego token.
- Załaduj wcześniej zapisane XML lub zakodowane dane do tego tokena.
- Pozwól widgetowi odczytać i edytować adnotacje sesji.
- Pobierz XML przy użyciu
GetAnnotationXML(token), gdy aplikacja zdecyduje się na utrwalenie. - Wyeksportuj PDF/PNG, gdy wymagany jest spłaszczony plik wyjściowy.
- Zamknij sesję dokumentu.
Nie używaj nieprzezroczystego tokena widoku jako stałego identyfikatora adnotacji. Powiąż utrwalone dane adnotacji z własnymi identyfikatorami dokumentu i wersji.
Uwagi dotyczące bezpieczeństwa i renderowania
- Żądania adnotacji używają takiego samego zabezpieczenia sesji/tokenu jak żądania stron.
- Względny
ImageAnnotationURL jest rozwiązywany z hosta żądania i musi pozostać dostępny dla serwera w czasie renderowania. - Należy walidować i kontrolować każdy podany przez użytkownika adres URL obrazu, aby uniknąć fałszywych żądań po stronie serwera.
- Eksporty stosują tę samą decyzję o licencji/znaku wodnym co renderowanie stron na ekranie.
- Duże ładunki odręczne i eksporty w wysokiej rozdzielczości zwiększają zużycie pamięci; testuj realistyczne dokumenty i wartości przybliżenia.
Rozwiązywanie problemów
| Objaw | Sprawdź |
|---|---|
| Wstążka adnotacji jest nieobecna | Annotation capability oraz cztery flagi CSS/skryptu adnotacji |
| Callback zapisu zgłasza błąd | Wygaśnięcie tokenu/sesji oraz middleware BasePath |
| Adnotacje C# nie pojawiają się | Numeracja stron zaczyna się od jednego i dane zostały załadowane do aktywnego tokenu |
| Adnotacja obrazu pojawia się na ekranie, ale nie w eksporcie | Serwer może dotrzeć do adresu URL obrazu podczas renderowania |
| Ponownie otwarty dokument nie ma adnotacji | Zachowaj XML/dane poza sesją przeglądarki, a następnie załaduj je do nowego tokenu |
Czy ta strona była pomocna?