הערות

הוסף תמיכה בהערות לצופה

הערות ב‑Doconut פועלות בשני כיוונים: משתמשים מציירים אותן בווידג'ט של הדפדפן והשרת שומר אותן לפי עמוד, או שהקוד שלך בונה אותן באופן תכנותי וטוען אותן למפגש פתוח. בכל מקרה הן מוצגות על העמודים וניתן לשלבן ביצוא PDF/PNG.

תמיכת ההערות מוגבלת על‑ידי יכולת הרישיון Annotation (ניתנת אוטומטית תחת רישיון זמני פעיל).

הפעל את ממשק ההערות

הערה היא מודול של Viewer, לא סרגל כלים עצמאי. על הדף המלא לכלול את משאבי ה‑Viewer, סרגל הכלים של Viewer, הרכבה של Viewer, ואת objViewer שהאותחל; לאחר מכן רצועת ההערה (Annotation Ribbon) מותקנת ומחוברת לאותו מופע.

הפץ את חבילות ההערה יחד עם חבילות הצופה — הן מוגבלות ברישיון, ולכן התגים מופיעים רק כאשר היכולת זמינה:

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 של הרצועה בתוך annBarMount; אינך צריך להעתיק את הכפתורים או את מרקאפ הדיאלוג שלה. אתחל תחילה את docViewer, ולאחר מכן צור את הרצועה רק כאשר השרת מאשר שההערה מורשית:

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>

שמירה מהרצועה מפרסמת נתונים דרך המידלוור (AnnSave), השומר אותם במפגש המסמך לפי עמוד. טעינה (AnnLoad) מתרחשת אוטומטית כאשר עמוד עם הערות מוצג. ארבעת קריאות הקול onAnn* משמרות את סנכרון הרצועה עם מחזור החיים של הצופה.

פתח וסגור אותה מכל סרגל כלים של Viewer שבבעלות המארח:

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

ממשק ה‑API הציבורי של הרצועה הוא:

מתודהמטרה
attach(objViewer)מחבר את ה‑Ribbon לצופה שהותחל; נדרש פעם אחת
open() / close()כניסה או יציאה ממצב עריכת ההערות
reset()מחזיר את ה‑Ribbon למצב סגור, ללא עריכה
isOpen() / annotating()קרא את מצב ה‑Ribbon / את מצב עריכת ההערות של הצופה
reopenEditable()טען מחדש את ההערות של העמוד הנוכחי כאובייקטים שניתנים לעריכה
updateActionState()רענן את זמינות בקרות השמירה/מחיקה לאחר שינויי המארח
headerSlot()קבל את משבצת ההרחבה האופציונלית בכותרת לבקרות של המארח

onStatus, onToast, onLayout, onEditStart, ו‑onEditEnd הם קריאות חזרה אופציונליות של המארח. האובייקט endpoints יכול בנוסף לספק exportPdf, exportPng, imageUpload, ו‑imageList; בקרות ללא נקודת קצה מוגדרת נשארות מוסתרות. עבור רצף האתחול המשולב של Viewer, Search וההערה, ראה התחלה מהירה.

חבילת ההערה מוסיפה את כלי הכתיבה בדפדפן, אך הנתונים עדיין שייכים למפגש המסמך בצד השרת המזוהה על‑ידי הטוקן. פתיחה מחדש של המקור יוצרת מפגש חדש; שמור את ה‑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. כתובת יחסית נפתרת ביחס למארח הבקשה כאשר האנוטציה מתווספת (רק משיכת התמונה מתרחשת בזמן השריפה) — היא חייבת להיות נגישה מהשרת (למשל קובץ תחת wwwroot המוגש על‑ידי UseStaticFiles)

ממשק ה‑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).

ייצוא עם אנוטציות משולבות

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. סגור את מפגש המסמך.

אל תשתמש בטוקן הצופה האופקי כמזהה קבוע לאנוטציה. קשר את נתוני האנוטציה השמורים עם מזהי המסמך והגרסה שלך.

הערות אבטחה והצגה

  • בקשות ההערה משתמשות באותה אבטחת session/token כמו בקשות דף.
  • כתובת URL יחסית של ImageAnnotation נפתרת מה‑host של הבקשה ויש להישאר נגישה לשרת בזמן הבערה.
  • יש לאמת ולשלוט בכל כתובת URL של תמונה שמסופקת על ידי המשתמש כדי למנוע זיוף בקשות בצד השרת.
  • ייצוא משתמש באותו החלטת רישיון/סימן מים מותאם כמו הצגת דף על המסך.
  • מטענים חופשיים גדולים וייצוא ברזולוציה גבוהה מגדילים את השימוש בזיכרון; יש לבדוק מסמכים מציאותיים וערכי זום.

פתרון בעיות

תסמיןבדיקה
סרגל ההערות חסריכולת Annotation והארבעה דגלי CSS/סקריפט של ההערות
קריאת חזרה של שמירה מדווחת על שגיאהתפוגת Token/session ו‑middleware BasePath
הערות C# אינן מופיעותמספור העמודים מתחיל מ‑1 והנתונים נטענו לטוקן הפעיל
הערת תמונה מופיעה על המסך אך לא בייצואהשרת יכול לגשת לכתובת URL של התמונה בזמן הבערה
מסמך שנפתח מחדש אין בו הערותשמרו XML/נתונים מחוץ למפגש הצופה, ואז טענו אותם לטוקן החדש

האם דף זה היה מועיל?