يعد عارض نشاط 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.
الميزات الافتراضية لهذا العارض هي التالية:
سيقوم إطار العمل تلقائيًا باستدعاء طريقة 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); }
سيتم الرسم بهذه الطريقة:
// 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 للرسم على مستوى البكسل.
// 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); }
// 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); }
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3