Anotasi

Tambahkan dukungan anotasi ke penampil

Anotasi di Doconut bekerja dalam dua arah: pengguna menggambarnya di widget peramban dan server menyimpannya per halaman, atau kode Anda membangunnya secara programatis dan memuatnya ke dalam sesi yang terbuka. Bagaimanapun, mereka ditampilkan pada halaman dan dapat dibakar ke dalam ekspor PDF/PNG.

Dukungan anotasi dibatasi oleh kemampuan lisensi Annotation (diberikan secara otomatis di bawah lisensi Temporary yang aktif).

Aktifkan UI anotasi

Anotasi adalah modul Viewer, bukan toolbar mandiri. Halaman lengkap harus menyertakan sumber daya Viewer, toolbar Viewer, mount Viewer, dan objViewer yang diinisialisasi; Ribbon Anotasi kemudian dipasang dan dilampirkan ke instance yang sama.

Keluarkan bundel anotasi bersamaan dengan bundel penampil — mereka dibatasi lisensi, sehingga tag hanya muncul ketika kemampuan tersedia:

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

Pertahankan komposisi Viewer lengkap terlihat dalam markup:

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>

Bundel Anotasi menghasilkan DOM Ribbon di dalam annBarMount; Anda tidak perlu menyalin tombol atau markup dialognya. Inisialisasikan docViewer terlebih dahulu, lalu buat Ribbon hanya ketika server mengonfirmasi bahwa Anotasi berlisensi:

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

Menyimpan dari Ribbon mengirim data melalui middleware (AnnSave), yang menyimpannya dalam sesi dokumen per halaman. Memuat (AnnLoad) terjadi secara otomatis ketika halaman dengan anotasi dirender. Empat callback onAnn* menjaga Ribbon tetap sinkron dengan siklus hidup penampil.

Buka dan tutup dari toolbar Viewer yang dimiliki host mana pun:

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

API Ribbon publik adalah:

MetodeTujuan
attach(objViewer)Hubungkan Ribbon ke penampil yang diinisialisasi; diperlukan satu kali
open() / close()Masuk atau keluar dari penyuntingan anotasi
reset()Kembalikan Ribbon ke keadaan tertutup, tidak dalam penyuntingan
isOpen() / annotating()Baca status Ribbon / status penyuntingan anotasi penampil
reopenEditable()Muat ulang anotasi halaman saat ini sebagai objek yang dapat diedit
updateActionState()Segarkan ketersediaan kontrol simpan/hapus setelah perubahan host
headerSlot()Dapatkan slot ekstensi header opsional untuk kontrol yang dimiliki host

onStatus, onToast, onLayout, onEditStart, dan onEditEnd adalah callback host opsional. Objek endpoints dapat tambahan menyediakan exportPdf, exportPng, imageUpload, dan imageList; kontrol tanpa endpoint yang dikonfigurasi tetap disembunyikan. Untuk urutan startup gabungan Viewer, Search, dan Annotation, lihat Mulai Cepat.

Bundel anotasi menambahkan alat authoring peramban, tetapi data masih milik sesi dokumen sisi server yang diidentifikasi oleh token. Membuka kembali sumber menciptakan sesi baru; simpan XML atau amplop anotasi yang terenkode dalam aplikasi Anda jika anotasi harus bertahan melampaui masa hidup sesi.

Membuat anotasi di C#

Dapatkan manajer yang terikat pada sesi terbuka, tambahkan anotasi, dan muat mereka (dengan using Doconut.Annotations; untuk tipe dan using System.Drawing; untuk 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();
});

Jenis Anotasi

Semua tipe berada di Doconut.Annotations dan mewarisi dari BaseAnnotation (nomor halaman + Rectangle pembatas):

TipeCatatan
StampAnnotationCap teks dengan ukuran font, border, warna; mendukung Opacity, Rotate
NoteAnnotationCatatan tempel dengan teks, warna latar belakang, ukuran font, TitleColor
RectangleAnnotationBorder + warna isi, Title/ShowTitle
CircleAnnotationBorder + isi, ShowBorder
EllipseAnnotationBorder + isi, ShowBorder
TriangleAnnotationWarna border, BackColor, ShowBorder
LineAnnotationGaris lurus dengan lebar dan warna
ArrowAnnotationGaris dengan kepala panah; dapat diatur Direction (tipe ArrowDirection, arah kompas, default E)
FreehandAnnotationGaris bebas dari titik FreehandData yang terenkode
ImageAnnotationGambar dari URL. URL relatif diresolusikan terhadap host permintaan saat anotasi ditambahkan (hanya pengambilan gambar terjadi pada saat pembakaran) — harus dapat dijangkau dari server (misalnya file di bawah wwwroot yang disajikan oleh UseStaticFiles)

API AnnotationManager

AnggotaTujuan
Add(BaseAnnotation)Antrian sebuah anotasi
GetAnnotations() / GetAnnotations(int page)Periksa apa yang dimiliki manajer
ClearAnnotations() / ClearAnnotations(int page)Hapus semua / per halaman
GetAnnotationData() / GetAnnotationData(int page)String data anotasi terenkode — sebuah envelope Base64 (apa yang dikonsumsi widget)
GetAnnotationXml()Bentuk XML

Viewer mencerminkan operasi muat/baca terhadap sesi: LoadAnnotationData(token, manager) atau LoadAnnotationData(token, encodedData) (envelope Base64 dari GetAnnotationData()), LoadAnnotationXML(token, xml), GetAnnotationXML(token).

Ekspor dengan anotasi terbakar

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

Ekspor menggunakan pembakar yang sama seperti rendering di layar, sehingga apa yang dilihat pengguna adalah apa yang terdapat dalam file.

Alur kerja Persistensi

  1. Buka dokumen dan dapatkan tokennya.
  2. Muat XML atau data terenkode yang sebelumnya disimpan ke dalam token tersebut.
  3. Biarkan widget membaca dan mengedit anotasi sesi.
  4. Ambil XML dengan GetAnnotationXML(token) ketika aplikasi Anda memutuskan untuk menyimpan.
  5. Ekspor PDF/PNG ketika diperlukan deliverable yang sudah diratakan.
  6. Tutup sesi dokumen.

Jangan gunakan token viewer yang tidak transparan sebagai pengidentifikasi anotasi permanen. Kaitkan data anotasi yang disimpan dengan dokumen dan pengidentifikasi versi Anda sendiri.

Catatan Keamanan dan Rendering

  • Permintaan anotasi menggunakan keamanan sesi/token yang sama seperti permintaan halaman.
  • URL ImageAnnotation relatif diselesaikan dari host permintaan dan harus tetap dapat dijangkau oleh server saat proses pembakaran.
  • Validasi dan kontrol setiap URL gambar yang diberikan pengguna untuk menghindari pemalsuan permintaan sisi server.
  • Ekspor menerapkan keputusan lisensi/custom-watermark yang sama seperti rendering halaman di layar.
  • Payload bebas tangan yang besar dan ekspor resolusi tinggi meningkatkan penggunaan memori; uji dokumen realistis dan nilai zoom.

Pemecahan Masalah

GejalaPemeriksaan
Pita anotasi tidak munculkapabilitas Annotation dan empat flag CSS/script anotasi
Callback penyimpanan melaporkan errorkedaluwarsa token/sesi dan middleware BasePath
Anotasi C# tidak munculpenomoran halaman dimulai dari satu dan data dimuat ke token aktif
Anotasi gambar muncul di layar tetapi tidak dalam eksporserver dapat menjangkau URL gambar selama proses pembakaran
Dokumen yang dibuka kembali tidak memiliki anotasipersist XML/data di luar sesi viewer, lalu muat ke token baru

Apakah halaman ini membantu?