甘特圖活動渲染器是 ScheduleJS 檢視器的主要渲染器。本文將討論它的建構方式以及該活動渲染器的特殊性。
建立渲染器類別的第一步是透過擴展高階框架類別來繼承屬性和方法。
我們只想透過開始和結束時間維度來表示任務。用於執行此操作的 ScheduleJS 基本渲染器類別是 ActivityBarRenderer 類別。
我們需要向ActivityBarRenderer 類別提供自訂類型參數,以便可以存取自訂Row 和Activity 類別提供的屬性和方法使用基類API 。
讓我們創建 ScheduleJsViewerTaskActivityRenderer 類來在各自的 ScheduleJsViewerTaskRow 中繪製每個 ScheduleJsViewerTaskActivity。
// 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<ScheduleJsViewerTaskActivity, ScheduleJsViewerTaskRow> { }
照原樣,渲染器已經可以註冊為使用 ActivityBarRenderer 的預設行為來繪製我們的活動。現在讓我們深入了解如何自訂它。
在 ScheduleJS 中,ActivityRenderer 是我們使用 Graphics API 以編程方式註冊的類,用於在其 Row 上繪製特定的 Activity。為了組織我們的 ScheduleJsViewerTaskActivityRenderer,我們將其程式碼分為三個部分:
屬性是將在整個渲染器中重複使用的常數。按原樣,這些屬性只能在渲染器程式碼中直接編輯。我們可以想像一個特定的螢幕,使用者可以在其中直接在 UI 中修改這些設定。
// 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;
建構子與我們的渲染器生命週期方法緊密耦合。在 ScheduleJS 檢視器中,我們決定在使用者切換螢幕時實例化渲染器以定義特殊性,並在實作此渲染器的每個標籤中重複使用我們的程式碼。這意味著每次使用者選擇具有此渲染器的畫面時都會運行建構函數。
// Constructor // The renderer requires the graphics and the current tab variable constructor(graphics: GraphicsBase<ScheduleJsViewerTaskRow>, 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<ScheduleJsViewerTaskActivity>, 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); }
繪圖將這樣進行:
讓我們仔細看看如何透過使用 _drawParentActivity 方法設計自己的方法來自由繪製您的 Activity。
// Draw the parent activity private _drawParentActivity(activityRef: ActivityRef<ScheduleJsViewerTaskActivity>, 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來定義我們的繪製策略。此方法中完成的唯一與框架相關的操作是為當前父 Activity 建立一些新的 ActivityBounds。
框架使用ActivityBounds在底層建立一個地圖來註冊螢幕上的所有活動。這張地圖透過提供類似元素的邏輯來幫助開發人員建立基於準確資訊的進階使用者體驗,同時利用 HTMLCanvas API.
的效能The draw elements methods like _drawParentActivityStartTriangle rely on the CanvasRenderingContext2D API to draw at the pixel level.
// Draw the start triangle element of the parent activity private static _drawParentActivityStartTriangle(ctx: CanvasRenderingContext2D, x: number, y: number, triangleWidth: number, triangleHeight: number): void { 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(); }
To register your brand-new renderer, use the graphics.setActivityRenderer method:
// Register the renderer graphics.setActivityRenderer(ScheduleJsViewerTaskActivity, GanttLayout, new ScheduleJsViewerTaskActivityRenderer(graphics, currentRibbonMenuTab));
To see the video of the final result you can go to see: Building an ActivityRenderer
以上是建構一個 ActivityRenderer的詳細內容。更多資訊請關注PHP中文網其他相關文章!