حاشیه‌نویسی‌ها

پشتیبانی از حاشیه‌نویسی را به نمایشگر اضافه کنید

حاشیه‌نویسی‌ها در Doconut به دو جهت کار می‌کنند: کاربران آن‌ها را در ویجت مرورگر می‌کشند و سرور آن‌ها را به‌صورت صفحه‌ای ذخیره می‌کند، یا کد شما آن‌ها را به‌صورت برنامه‌نویسی ساخته و به یک جلسه باز بارگذاری می‌کند. به هر حال، این‌ها در صفحات رندر می‌شوند و می‌توانند در خروجی‌های PDF/PNG سوزانده شوند.

پشتیبانی از حاشیه‌نویسی توسط قابلیت لایسنس Annotation محدود شده است (به‌صورت خودکار تحت یک لایسنس موقت فعال اعطا می‌شود).

فعال‌سازی رابط کاربری حاشیه‌نویسی

حاشیه‌نویسی یک ماژول Viewer است، نه یک نوار ابزار مستقل. صفحه کامل باید شامل منابع Viewer، نوار ابزار Viewer، نقطه نصب Viewer و objViewer اولیه‌شده باشد؛ سپس نوار Ribbon حاشیه‌نویسی نصب و به همان نمونه متصل می‌شود.

باندل‌های حاشیه‌نویسی را همراه با باندل‌های viewer صادر کنید — آن‌ها تحت لایسنس هستند، بنابراین برچسب‌ها فقط زمانی ظاهر می‌شوند که قابلیت موجود باشد:

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

ترکیب کامل Viewer را در مارکاپ قابل مشاهده نگه دارید:

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>

باندل حاشیه‌نویسی DOM نوار Ribbon را داخل annBarMount تولید می‌کند؛ نیازی به کپی کردن دکمه‌ها یا مارکاپ دیالوگ آن نیست. ابتدا docViewer را مقداردهی کنید، سپس نوار Ribbon را فقط زمانی ایجاد کنید که سرور تأیید کند حاشیه‌نویسی لایسنس‌دار است:

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>

ذخیره‌سازی از نوار Ribbon داده‌ها را از طریق میدل‌ویر (AnnSave) ارسال می‌کند، که آن را در جلسه سند به‌ازای هر صفحه ذخیره می‌سازد. بارگذاری (AnnLoad) به‌صورت خودکار زمانی که صفحه‌ای با حاشیه‌نویسی رندر می‌شود، اتفاق می‌افتد. چهار کال‌بک onAnn* نوار Ribbon را با چرخه حیات viewer همگام نگه می‌دارند.

از هر نوار ابزار Viewer متعلق به میزبان می‌توانید آن را باز یا بسته کنید:

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

API عمومی نوار Ribbon عبارت است از:

متدهدف
attach(objViewer)اتصال Ribbon به viewer اولیه‌شده؛ یک بار مورد نیاز
open() / close()ورود یا خروج از حالت ویرایش حاشیه‌نویسی
reset()بازگرداندن Ribbon به حالت بسته و غیر ویرایشی
isOpen() / annotating()خواندن وضعیت Ribbon / وضعیت ویرایش حاشیه‌نویسی viewer
reopenEditable()بارگذاری مجدد حاشیه‌نویسی‌های صفحه جاری به‌عنوان اشیای قابل ویرایش
updateActionState()به‌روزرسانی در دسترس بودن کنترل‌های ذخیره/حذف پس از تغییرات میزبان
headerSlot()دریافت اسلات اختیاری سرصفحه برای کنترل‌های متعلق به میزبان

onStatus, onToast, onLayout, onEditStart, و onEditEnd کال‌بک‌های اختیاری میزبان هستند. شیء endpoints می‌تواند به‌علاوه exportPdf, exportPng, imageUpload, و imageList را فراهم کند؛ کنترل‌هایی که endpoint پیکربندی‌شده ندارند مخفی می‌مانند. برای توالی راه‌اندازی ترکیبی Viewer، Search و Annotation، به شروع سریع (Quick Start) مراجعه کنید.

باندل حاشیه‌نویسی ابزارهای نویسندگی مرورگر را اضافه می‌کند، اما داده‌ها همچنان به جلسه سند سمت سرور که با توکن شناسایی می‌شود تعلق دارند. بازگشایی منبع یک جلسه جدید ایجاد می‌کند؛ اگر حاشیه‌نویسی‌ها باید پس از پایان عمر جلسه حفظ شوند، XML یا پاکت حاشیه‌نویسی رمزگذاری‌شده را در برنامه خود ذخیره کنید.

ساخت حاشیه‌نویسی‌ها در C#

یک مدیر متصل به جلسه باز دریافت کنید، حاشیه‌نویسی‌ها را اضافه کنید و آن‌ها را بارگذاری کنید (با using Doconut.Annotations; برای انواع و using System.Drawing; برای 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();
});

انواع حاشیه‌نویسی

تمام انواع در 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 relative در زمان افزودن حاشیه‌نویسی نسبت به میزبان درخواست حل می‌شود (فقط دریافت تصویر در زمان سوزاندن انجام می‌شود) — باید از سمت سرور قابل دسترسی باشد (مثلاً فایلی زیر wwwroot که توسط UseStaticFiles سرو می‌شود)

API مدیریت حاشیه‌نویسی

عضوهدف
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).

خروجی با حاشیه‌نویسی‌های سوزانده‌شده

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

خروجی‌ها از همان موتور سوزاندن که برای رندر روی صفحه استفاده می‌شود بهره می‌برند، بنابراین آنچه کاربران می‌بینند همان چیزی است که فایل شامل آن می‌شود.

جریان کار حفظ‌سازی

  1. سند را باز کنید و توکن آن را دریافت کنید.
  2. XML یا داده‌های رمزگذاری‌شده قبلاً ذخیره‌شده را به آن توکن بارگذاری کنید.
  3. به ویجت اجازه دهید حاشیه‌نویسی‌های جلسه را بخواند و ویرایش کند.
  4. XML را با GetAnnotationXML(token) دریافت کنید وقتی برنامه شما تصمیم به حفظ دارد.
  5. PDF/PNG را خروجی بگیرید وقتی یک تحویل مسطح مورد نیاز است.
  6. جلسه سند را ببندید.

از توکن viewer نامشخص به‌عنوان شناسه دائمی حاشیه‌نویسی استفاده نکنید. داده‌های حاشیه‌نویسی حفظ‌شده را با شناسه‌های سند و نسخه خودتان مرتبط کنید.

نکات امنیتی و رندرینگ

  • درخواست‌های حاشیه‌نویسی از همان امنیت جلسه/توکن مانند درخواست‌های صفحه استفاده می‌کنند.
  • یک URL ImageAnnotation relative از میزبان درخواست حل می‌شود و باید در زمان سوزاندن برای سرور قابل دسترسی باقی بماند.
  • URL تصویر ارائه‌شده توسط کاربر را اعتبارسنجی و کنترل کنید تا از جعل درخواست سمت سرور جلوگیری شود.
  • خروجی‌ها همان تصمیم لایسنس/آب‌نشان سفارشی را که برای رندر صفحه روی صفحه اعمال می‌شود، اعمال می‌کنند.
  • بارهای بزرگ حاشیه‌نویسی آزاد و خروجی‌های با وضوح بالا مصرف حافظه را افزایش می‌دهند؛ اسناد واقعی و مقادیر زوم را تست کنید.

عیب‌یابی

علائمبررسی
نوار حاشیه‌نویسی گم شده استقابلیت Annotation و چهار پرچم CSS/اسکریپت حاشیه‌نویسی
کال‌بک ذخیره خطا گزارش می‌دهدانقضای توکن/جلسه و BasePath میدل‌ویر
حاشیه‌نویسی‌های C# ظاهر نمی‌شوندشماره‌گذاری صفحات از یک شروع می‌شود و داده‌ها به توکن فعال بارگذاری شده‌اند
حاشیه‌نویسی تصویر روی صفحه نمایش می‌شود اما در خروجی نیستسرور می‌تواند در زمان سوزاندن به URL تصویر دسترسی داشته باشد
سند باز شده مجدداً حاشیه‌نویسی نداردXML/داده‌ها را خارج از جلسه viewer حفظ کنید، سپس به توکن جدید بارگذاری کنید

آیا این صفحه مفید بود؟