"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > بناء عارض النشاط

بناء عارض النشاط

تم النشر بتاريخ 2024-08-05
تصفح:780

يعد عارض نشاط Gantt هو العارض الرئيسي لعارض TableJS. ستناقش هذه المقالة كيفية إنشائها وما هي خصوصيات عارض النشاط هذا.

كيفية بناء فئة العارض المخصصة

الخطوة الأولى لبناء فئة العارض هي وراثة السمات والأساليب عن طريق توسيع فئة إطارية ذات ترتيب أعلى.

نريد تمثيل المهام فقط من خلال أبعاد وقت البدء والانتهاء. فئة العارض الأساسية لـ TableJS للقيام بذلك هي فئة ActivityBarRenderer.

نحتاج إلى توفير وسيطات من النوع المخصص لفئة ActivityBarRenderer بحيث يمكن الوصول إلى السمات والأساليب التي توفرها فئات Row وActivity المخصصة لدينا باستخدام واجهة برمجة التطبيقات (API) من الفئة الأساسية.

فلنقم بإنشاء فئة ScheduleJsViewerTaskActivityRenderer لرسم كل ScheduleJsViewerTaskActivity في ScheduleJsViewerTaskRow.

// Import the base ActivityBarRenderer class from ScheduleJS
import {ActivityBarRenderer} from "schedule";

// Import our custom Activity and Row types
import {ScheduleJsViewerTaskActivity} from "...";
import {ScheduleJsViewerTaskRow} from "...";

// Create our custom renderer by extending the ActivityBarRenderer class
export class ScheduleJsViewerTaskActivityRenderer extends ActivityBarRenderer { }

كما هو، يمكن بالفعل تسجيل العارض لرسم أنشطتنا باستخدام السلوك الافتراضي لـ ActivityBarRenderer. الآن دعونا نتعمق في كيفية تخصيصه.

العمارة الأساسية

في جدولة JS، يعد ActivityRenderer فئة نقوم بتسجيلها برمجيًا باستخدام Graphics API لرسم نشاط محدد في صف. لتنظيم ScheduleJsViewerTaskActivityRenderer، سنقوم بفصل الكود الخاص به إلى ثلاثة أقسام:

  • ستحتوي السمات على متغيرات تتيح لنا تغيير السلوك لإجراء رسم معين.
  • سيسمح لنا المُنشئ بتحديد الحالة الافتراضية للعارض.
  • ستحتوي طرق الرسم على جميع التعليمات الخاصة برسم أنشطتنا على القماش.

صفات

السمات هي ثوابت سيتم إعادة استخدامها في جميع أنحاء العارض. كما هي، سيتم تحرير هذه الخصائص مباشرة في كود العارض فقط. يمكننا أن نتخيل شاشة معينة حيث يمكن للمستخدم تعديل هذه الإعدادات مباشرة في واجهة المستخدم.

// Attributes

// Pixels sizings
private readonly _parentActivityTrianglesWidthPx: number = 5;
private readonly _parentActivityTrianglesHeightPx: number = 8;
private readonly _defaultLineWidthPx: number = 0.5;

// Colors palette
private readonly _parentActivityColor: string = Color.GRAY.toCssString();
private readonly _strokeColor: string = Color.BLACK.toCssString();
private readonly _defaultActivityGreen: Color = Color.rgb(28, 187, 158);
private readonly _defaultActivityBlue: Color = Color.rgb(53, 152, 214);
private readonly _onHoverFillColor: string = Color.ORANGE.toCssString();

// Opacity ratio for baseline activities
private readonly _baselineOpacityRatio: number = 0.6;

البناء

يرتبط المُنشئ بإحكام بأسلوب دورة حياة العارض الخاص بنا. في عارض TableJS، قررنا إنشاء مثيل للعارض عندما يقوم المستخدم بتبديل الشاشات لتحديد المواصفات وإعادة استخدام الكود الخاص بنا في كل علامة تبويب تقوم بتنفيذ هذا العارض. وهذا يعني أن وظيفة المنشئ يتم تشغيلها في كل مرة يحدد فيها المستخدم شاشة تعرض هذا العارض.

// Constructor

// The renderer requires the graphics and the current tab variable
constructor(graphics: GraphicsBase,
            private _currentRibbonMenuTab: ScheduleJsViewerRibbonMenuTabsEnum) {

  // The ActivityBarRenderer class requires the graphics and a name for the renderer
  super(graphics, ScheduleJsViewerRenderingConstants.taskActivityRendererName);

  // Default fill color when hovering an activity
  this.setFillHover(Color.web(this._onHoverFillColor));

  // Default stroke color when hovering an activity
  this.setStrokeHover(Color.BLACK);

  // Default stroke color
  this.setStroke(Color.BLACK);

  // Default thickness
  this.setLineWidth(this._defaultLineWidthPx);

  // Default bar height
  this.setBarHeight(8);

  // Default fill color based on current tab 
  switch (_currentRibbonMenuTab) {
    // Change color for the WBS tab
    case ScheduleJsViewerRibbonMenuTabsEnum.WBS:
      this._parentActivityColor = ScheduleJsViewerColors.brown;
      this.setFill(this._defaultActivityBlue);
      break;
    default:
      this._parentActivityColor = Color.GRAY.toCssString();
      this.setFill(this._defaultActivityGreen);
      break;
  }

}

يتم توريث setFill وsetStroke وsetFillHover وsetStrokeHover وsetLineWidth وsetBarHeight واستخدامها لتغيير خصائص العرض الافتراضية لفئة ActivityBarRenderer.

الميزات الافتراضية لهذا العارض هي التالية:

  • لون مخصص عند تمرير الأنشطة
  • خط أسود (لحدود النشاط)
  • سمك خط السكتة الدماغية 0.5 بكسل
  • ارتفاع شريط النشاط 8 بكسل
  • لون التعبئة الشرطي: الأزرق للأطفال والبني للآباء في علامة التبويب WBS الأخضر للأطفال والرمادي للآباء في علامات التبويب الأخرى

رسم

سيقوم إطار العمل تلقائيًا باستدعاء طريقة drawActivity لعرض أنشطتنا على اللوحة القماشية. يتم ملء جميع معلماته ديناميكيًا، مما يسمح لك بالتفاعل في الوقت الفعلي مع الحالة الحالية لأنشطتك.

// Main drawing method

drawActivity(activityRef: ActivityRef,
             position: ViewPosition,
             ctx: CanvasRenderingContext2D,
             x: number,
             y: number,
             w: number,
             h: number,
             selected: boolean,    
             hover: boolean,
             highlighted: boolean,
             pressed: boolean     
            ): ActivityBounds {    // This method has to return ActivityBounds

    // True if current activity includes a comparison task
    const hasModifications = !!activityRef.getActivity().diffTask;

    // True if current row has children
    const isParent = activityRef.getRow().getChildren().length;

    // Set colors dynamically
    this._setActivityColor(activityRef, hasModifications);

    // Draw text
    this._drawActivityText(activityRef, ctx, x, y, w, h, hasModifications);

    // Run a custom method to draw parent activities or delegate to the default method
    return isParent
      ? this._drawParentActivity(activityRef, ctx, x, y, w, h, hover, hasModifications)
      : super.drawActivity(activityRef, position, ctx, x, y, w, h, selected, hover, highlighted, pressed);
  }

سيتم الرسم بهذه الطريقة:

  • احصل على معلومات حول النشاط والصف الحالي باستخدام ActivityRef API
  • قم بتعيين الألوان ديناميكيًا باستخدام طريقة _setActivityColor الخاصة بنا
  • ارسم نص النشاط باستخدام طريقة _drawActivityText الخاصة بنا
  • رسم النشاط نفسه بناءً على طريقتين: طريقة _drawParentActivity لرسم الوالدين طريقة super.drawActivity الافتراضية ActivityBarRenderer لرسم الأطفال
طرق رسم النشاط المخصص

دعونا نلقي نظرة فاحصة على كيفية رسم نشاطك بحرية من خلال تصميم أساليبك الخاصة باستخدام طريقة _drawParentActivity.


// ارسم النشاط الأصلي خاص _drawParentActivity(activityRef: ActivityRef, ctx: كانفاسRenderingContext2D، س: رقم، ص: رقم، ث: رقم، ح: رقم، تحوم: منطقية، hasModifications: boolean ): حدود النشاط { // ضبط الحشوة const topPadding = h / 3.5; const leftPadding = 1; // تعيين CanvasRenderingContext2D ctx.lineWidth = this._defaultLineWidthPx; إذا (تحوم) { ctx.fillStyle = this._onHoverFillColor; ctx.strokeStyle =schedulJsViewerColors.brown; } وإلا إذا (hasModifications) { ctx.fillStyle = Color.web(this._parentActivityColor).withOpacity(this._baselineOpacityRatio).toCssString(); ctx.strokeStyle = `rgba(0,0,0,${this._baselineOpacityRatio})`; } آخر { ctx.fillStyle = this._parentActivityColor; ctx.strokeStyle = this._strokeColor; } // رسم العناصر ScheduelJsViewerTaskActivityRenderer._drawParentActivityStartTriangle(ctx, x leftPadding, y topPadding, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx); ScheduelJsViewerTaskActivityRenderer._drawParentActivityBody(ctx, x leftPadding, y topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx); ScheduelJsViewerTaskActivityRenderer._drawParentActivityEndTriangle(ctx, x leftPadding, y topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx); // قم بإرجاع المواضع لتحديث المكان الذي يجب أن يستجيب فيه نشاطك إرجاع ActivityBounds جديدة (activityRef, x, y, w, h); }
// Draw the parent activity

private _drawParentActivity(activityRef: ActivityRef,
                            ctx: CanvasRenderingContext2D,
                            x: number,
                            y: number,
                            w: number,
                            h: number,
                            hover: boolean,
                            hasModifications: boolean
                           ): ActivityBounds {

    // Set padding
    const topPadding = h / 3.5;
    const leftPadding = 1;

    // Set CanvasRenderingContext2D
    ctx.lineWidth = this._defaultLineWidthPx;
    if (hover) {
      ctx.fillStyle = this._onHoverFillColor;
      ctx.strokeStyle = ScheduleJsViewerColors.brown;
    } else if (hasModifications) {
      ctx.fillStyle = Color.web(this._parentActivityColor).withOpacity(this._baselineOpacityRatio).toCssString();
      ctx.strokeStyle = `rgba(0,0,0,${this._baselineOpacityRatio})`;
    } else {
      ctx.fillStyle = this._parentActivityColor;
      ctx.strokeStyle = this._strokeColor;
    }

    // Draw elements
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityStartTriangle(ctx, x   leftPadding, y   topPadding, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityBody(ctx, x   leftPadding, y   topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityEndTriangle(ctx, x   leftPadding, y   topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);

    // Return positions to update where your activity should be responsive
    return new ActivityBounds(activityRef, x, y, w, h);
  }
نستخدم هنا مباشرة

HTMLCanvas API لتحديد استراتيجية الرسم لدينا من خلال إعداد CanvasRenderingContex2D. العملية الوحيدة المتعلقة بإطار العمل التي يتم إجراؤها بهذه الطريقة هي إنشاء بعض ActivityBounds الجديدة للأصل الحالي Activity.

يقوم إطار العمل بإنشاء خريطة باستخدام

ActivityBounds أسفل الغطاء لتسجيل جميع الأنشطة على الشاشة. تساعد هذه الخريطة المطور من خلال توفير منطق يشبه العنصر لبناء تجارب مستخدم متقدمة بناءً على معلومات دقيقة مع الاستفادة من أداء HTMLCanvas API.

تعتمد أساليب عناصر الرسم مثل _drawParentActivityStartTriangle على

CanvasRenderingContext2D API للرسم على مستوى البكسل.

// ارسم عنصر مثلث البداية للنشاط الأصلي _drawParentActivityStartTriangle ثابت خاص (ctx: CanvasRenderingContext2D، س: رقم، ص: رقم، عرض المثلث: العدد، ارتفاع المثلث: العدد): باطلة { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x , y TriangleHeight); ctx.lineTo(x TriangleWidth, y); ctx.lineTo(x, y); ctx.fill(); ctx.stroke(); ctx. ClosePath(); }
// Draw the parent activity

private _drawParentActivity(activityRef: ActivityRef,
                            ctx: CanvasRenderingContext2D,
                            x: number,
                            y: number,
                            w: number,
                            h: number,
                            hover: boolean,
                            hasModifications: boolean
                           ): ActivityBounds {

    // Set padding
    const topPadding = h / 3.5;
    const leftPadding = 1;

    // Set CanvasRenderingContext2D
    ctx.lineWidth = this._defaultLineWidthPx;
    if (hover) {
      ctx.fillStyle = this._onHoverFillColor;
      ctx.strokeStyle = ScheduleJsViewerColors.brown;
    } else if (hasModifications) {
      ctx.fillStyle = Color.web(this._parentActivityColor).withOpacity(this._baselineOpacityRatio).toCssString();
      ctx.strokeStyle = `rgba(0,0,0,${this._baselineOpacityRatio})`;
    } else {
      ctx.fillStyle = this._parentActivityColor;
      ctx.strokeStyle = this._strokeColor;
    }

    // Draw elements
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityStartTriangle(ctx, x   leftPadding, y   topPadding, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityBody(ctx, x   leftPadding, y   topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityEndTriangle(ctx, x   leftPadding, y   topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);

    // Return positions to update where your activity should be responsive
    return new ActivityBounds(activityRef, x, y, w, h);
  }
النتيجة النهائية

لتسجيل العارض الجديد الخاص بك، استخدم طريقة graphics.setActivityRenderer:


// سجل العارض graphics.setActivityRenderer(ScheduleJsViewerTaskActivity, GanttLayout, newchedJsViewerTaskActivityRenderer(graphics,currentRibbonMenuTab));
// Draw the parent activity

private _drawParentActivity(activityRef: ActivityRef,
                            ctx: CanvasRenderingContext2D,
                            x: number,
                            y: number,
                            w: number,
                            h: number,
                            hover: boolean,
                            hasModifications: boolean
                           ): ActivityBounds {

    // Set padding
    const topPadding = h / 3.5;
    const leftPadding = 1;

    // Set CanvasRenderingContext2D
    ctx.lineWidth = this._defaultLineWidthPx;
    if (hover) {
      ctx.fillStyle = this._onHoverFillColor;
      ctx.strokeStyle = ScheduleJsViewerColors.brown;
    } else if (hasModifications) {
      ctx.fillStyle = Color.web(this._parentActivityColor).withOpacity(this._baselineOpacityRatio).toCssString();
      ctx.strokeStyle = `rgba(0,0,0,${this._baselineOpacityRatio})`;
    } else {
      ctx.fillStyle = this._parentActivityColor;
      ctx.strokeStyle = this._strokeColor;
    }

    // Draw elements
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityStartTriangle(ctx, x   leftPadding, y   topPadding, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityBody(ctx, x   leftPadding, y   topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);
    ScheduleJsViewerTaskActivityRenderer._drawParentActivityEndTriangle(ctx, x   leftPadding, y   topPadding, w, this._parentActivityTrianglesWidthPx, this._parentActivityTrianglesHeightPx);

    // Return positions to update where your activity should be responsive
    return new ActivityBounds(activityRef, x, y, w, h);
  }

brand-new renderer

لمشاهدة فيديو النتيجة النهائية يمكنك الذهاب لمشاهدة: إنشاء عارض الأنشطة

بيان الافراج تم نشر هذه المقالة على: https://dev.to/lenormor/building-an-activityrenderer-3o0?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] لحذفه
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3