הערות

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

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

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

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

ההערה היא מודול של 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">
    <!-- בקרות הצופה, כולל הכפתור הפותח Annotation -->
</nav>
<div id="annBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>

חבילת ההערות מייצרת את ה‑Ribbon DOM בתוך annBarMount; אין צורך להעתיק את הכפתורים או את תגיות הדיאלוג שלה. אתחל תחילה את docViewer, ולאחר מכן צור את ה‑Ribbon רק כאשר השרת מאשר שה‑Annotation מורשה:

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 שבבעלות המארח:

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

API הציבורי של ה‑Ribbon הוא:

מתודהמטרה
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, ו‑Annotation, ראה התחלה מהירה(Quick Start).

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

בניית אנוטציות ב‑C#

קבל מנהל הקשור למפגש הפתוח, הוסף אנוטציות, וטען אותן (עם using Doconut.Annotations; עבור הסוגים ו-using System.Drawing; עבור Rectangle/Color):

csharp
app.MapPost("/api/annotations/load-sample", (string token, Viewer viewer) =>
{
    // קשור למימדי העמוד של ההפעלה הפתוחה
    var manager = viewer.GetAnnotationManager(token);
    var pageCount = viewer.GetPageCount(token);

    // חותמת אחת לכל עמוד
    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));

    // טען לתוך ההפעלה — הווידג'ט משיג אותם דרך AnnLoad ו‑
    // renderer שורף אותם לתוך ייצואי תמונה/PDF.
    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 יחסי נפתר יחסית למארח הבקשה כאשר האנוטציה מתווספת (רק משיכת התמונה מתרחשת בזמן השריפה) — הוא חייב להיות נגיש מהשרת (למשל קובץ תחת 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 של כל העמודים עם ההערות משולבות עליהם
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");
});

// או ZIP של 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/script של ההערות
ה‑callback של השמירה מדווח על שגיאהפג תוקף של Token/session וה‑middleware BasePath
ההערות של C# אינן מופיעותמספור העמודים מתחיל מ‑1 והנתונים נטענו לטוקן הפעיל
הערת תמונה מופיעה על המסך אך לא בייצואהשרת יכול לגשת ל‑URL של התמונה בזמן הבערה
מסמך שנפתח מחדש אינו מכיל הערותשמור XML/נתונים מחוץ למפגש הצופה, ואז טען אותם לטוקן החדש

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