Annotationer

Lägg till stöd för annotationer i visaren

Annotationer i Doconut fungerar i två riktningar: användare ritar dem i webbläsarwidgeten och servern sparar dem per sida, eller så bygger din kod dem programatiskt och laddar dem in i en öppen session. I båda fallen renderas de på sidorna och kan brännas in i PDF/PNG‑exporter.

Stöd för annotationer styrs av licensfunktionen Annotation (tilldelas automatiskt under en aktiv temporär licens).

Aktivera annoterings‑UI

Annotation är en Viewer‑modul, inte ett fristående verktygsfält. Den kompletta sidan måste inkludera Viewer‑resurserna, Viewer‑verktygsfältet, Viewer‑monteringen och den initierade objViewer; Annotation‑Ribbon‑en monteras sedan och fästs på samma instans.

Skicka ut annoteringspaketen tillsammans med viewer‑paketen — de är licensstyrda, så taggarna visas endast när funktionen är tillgänglig:

html
@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
}))

Behåll den kompletta Viewer‑kompositionen synlig i markupen:

html
<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>

Annotation‑paketet genererar Ribbon‑DOM‑en inuti annBarMount; du behöver inte kopiera dess knappar eller dialog‑markup. Initiera docViewer först, skapa sedan Ribbon‑en endast när servern bekräftar att Annotation är licensierad:

html
<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>

Sparande från Ribbon skickar data via middleware (AnnSave), som lagrar den i dokument‑sessionen per sida. Laddning (AnnLoad) sker automatiskt när en sida med annotationer renderas. De fyra onAnn*‑återanropen håller Ribbon synkroniserad med viewer‑livscykeln.

Öppna och stäng den från vilket host‑ägda Viewer‑verktygsfält som helst:

javascript
annBar.open();
annBar.close();

Det offentliga Ribbon‑API:t är:

MetodSyfte
attach(objViewer)Anslut Ribbon till den initierade viewern; krävs en gång
open() / close()Påbörja eller avsluta annoteringsredigering
reset()Återställ Ribbon till dess stängda, icke‑redigerande tillstånd
isOpen() / annotating()Läs Ribbon‑tillståndet / viewerns annoteringsredigeringsstatus
reopenEditable()Ladda om den aktuella sidans annotationer som redigerbara objekt
updateActionState()Uppdatera tillgänglighet för spara/ta‑bort‑kontroller efter host‑ändringar
headerSlot()Hämta det valfria header‑utökning‑slottet för host‑ägda kontroller

onStatus, onToast, onLayout, onEditStart och onEditEnd är valfria host‑återanrop. endpoints‑objektet kan dessutom tillhandahålla exportPdf, exportPng, imageUpload och imageList; kontroller utan en konfigurerad endpoint förblir dolda. För den kombinerade Viewer‑, Search‑ och Annotation‑uppstartssekvensen, se Snabbstart.

Annoteringspaketet lägger till webbläsarens författarverktyg, men datan tillhör fortfarande server‑sidans dokument‑session identifierad av token. Att återöppna källan skapar en ny session; persistera XML‑ eller kodad annoterings‑omslag i din applikation om annotationer måste överleva bortom sessionens livstid.

Bygg annotationer i C#

Hämta en manager bunden till den öppna sessionen, lägg till annotationer och ladda dem (med using Doconut.Annotations; för typerna och using System.Drawing; för Rectangle/Color):

csharp
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();
});

Annotationstyper

Alla typer finns i Doconut.Annotations och ärver från BaseAnnotation (sidnummer + avgränsande Rectangle):

TypAnteckningar
StampAnnotationTextstämpel med teckenstorlek, kant, färg; stödjer Opacity, Rotate
NoteAnnotationKlistermärke med text, bakgrundsfärg, teckenstorlek, TitleColor
RectangleAnnotationKant‑ och fyllnadsfärger, Title/ShowTitle
CircleAnnotationKant‑ och fyllnad, ShowBorder
EllipseAnnotationKant‑ och fyllnad, ShowBorder
TriangleAnnotationKantfärg, BackColor, ShowBorder
LineAnnotationRaka linjen med bredd och färg
ArrowAnnotationLinje med pilspets; inställningsbar Direction (typ ArrowDirection, kompassriktningar, standard E)
FreehandAnnotationFri penseldragning från kodade FreehandData‑punkter
ImageAnnotationBild från en URL. En relativ URL löses upp mot begärans värd när annotationen läggs till (endast bildhämtning sker vid bränning) — den måste vara åtkomlig från servern (t.ex. en fil under wwwroot som serveras av UseStaticFiles)

AnnotationManager‑API:t

MedlemSyfte
Add(BaseAnnotation)Köa en annotation
GetAnnotations() / GetAnnotations(int page)Inspektera vad managern innehåller
ClearAnnotations() / ClearAnnotations(int page)Ta bort alla / per sida
GetAnnotationData() / GetAnnotationData(int page)Kodad annotation‑datat sträng — ett Base64‑överföringsomslag (vad widgeten konsumerar)
GetAnnotationXml()XML‑format

Viewer speglar ladd‑/läsningsoperationerna mot en session: LoadAnnotationData(token, manager) eller LoadAnnotationData(token, encodedData) (Base64‑överföringsomslaget från GetAnnotationData()), LoadAnnotationXML(token, xml), GetAnnotationXML(token).

Export med inbrända annotationer

csharp
// 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");
});

Export använder samma brännare som skärmrendering, så det användarna ser är det filen innehåller.

Arbetsflöde för beständighet

  1. Öppna dokumentet och hämta dess token.
  2. Ladda tidigare lagrad XML eller kodad data i den token.
  3. Låt widgeten läsa och redigera sessionens annotationer.
  4. Hämta XML med GetAnnotationXML(token) när din applikation bestämmer sig för att persistera.
  5. Exportera PDF/PNG när en platt leverans krävs.
  6. Stäng dokumentsessionen.

Använd inte den otydliga viewer‑token som en permanent annoteringsidentifierare. Koppla beständig annoteringsdata till dina egna dokument‑ och versionsidentifierare.

Säkerhets‑ och renderingsanteckningar

  • Annoteringsförfrågningar använder samma session-/token‑säkerhet som sidförfrågningar.
  • En relativ ImageAnnotation‑URL löses upp från begärans värd och måste vara åtkomlig för servern vid bränning.
  • Validera och kontrollera alla användargenererade bild‑URL:er för att undvika server‑sidig förfrågningsförfalskning.
  • Export använder samma licens-/anpassade vattenstämpel‑beslut som skärmrendering av sidor.
  • Stora frihands‑payloads och högupplösta export ökar minnesanvändning; testa realistiska dokument och zoomvärden.

Felsökning

SymtomKontroll
Annotation‑ribbon saknasAnnotation‑funktion och de fyra annotation‑CSS/script‑flaggorna
Spara‑återanrop rapporterar ett felToken-/session‑utgång och middleware BasePath
C#‑annotationer visas inteSidnumrering är en‑baserad och data laddades in i den aktiva token
Bildannotation visas på skärmen men inte i exportServern kan nå bild‑URL:en under bränning
Återöppnat dokument har inga annotationerPersistera XML/data utanför viewer‑sessionen, ladda sedan in den i den nya token

Var den här sidan till hjälp?