首頁 > web前端 > js教程 > 主體

建構一個 ActivityRenderer

王林
發布: 2024-07-16 21:19:14
原創
985 人瀏覽過

甘特圖活動渲染器是 ScheduleJS 檢視器的主要渲染器。本文將討論它的建構方式以及該活動渲染器的特殊性。

如何建立自訂渲染器類

建立渲染器類別的第一步是透過擴展高階框架類別來繼承屬性和方法。

我們只想透過開始和結束時間維度來表示任務。用於執行此操作的 ScheduleJS 基本渲染器類別是 ActivityBarRenderer 類別。

我們需要向ActivityBarRenderer 類別提供自訂類型參數,以便可以存取自訂RowActivity 類別提供的屬性和方法使用基類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 類別的預設渲染特性。

此渲染器的預設功能如下:

  • 懸停活動時的自訂顏色
  • 黑色線條(用於活動邊框)
  • 0.5 像素的描邊線
  • 活動欄高度為 8 像素
  • 條件填滿顏色: 在 WBS 選項卡中,藍色代表兒童,棕色代表父母 其他選項卡中的兒童為綠色,家長為灰色

繪畫

框架會自動呼叫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);
  }
登入後複製

繪圖將這樣進行:

  • 使用 ActivityRef API 獲取有關當前 ActivityRow 的信息
  • 使用我們的 _setActivityColor 方法動態設定顏色
  • 使用我們的 _drawActivityText 方法繪製活動文字
  • 使用兩種方法繪製活動本身: _drawParentActivity 方法繪製父母 super.drawActivity預設的ActivityBarRenderer方法來繪製children

自訂活動繪製方法

讓我們仔細看看如何透過使用 _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();
}
登入後複製

Final result

To register your brand-new renderer, use the graphics.setActivityRenderer method:

// Register the renderer

graphics.setActivityRenderer(ScheduleJsViewerTaskActivity, GanttLayout, new ScheduleJsViewerTaskActivityRenderer(graphics, currentRibbonMenuTab));

登入後複製

brand-new renderer

To see the video of the final result you can go to see: Building an ActivityRenderer

以上是建構一個 ActivityRenderer的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!