„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Erstellen eines ActivityRenderers

Erstellen eines ActivityRenderers

Veröffentlicht am 05.08.2024
Durchsuche:597

Der Gantt-Aktivitätsrenderer ist der Hauptrenderer des ScheduleJS Viewer. In diesem Artikel wird erläutert, wie er aufgebaut ist und welche Besonderheiten dieser Aktivitätsrenderer aufweist.

So erstellen Sie eine benutzerdefinierte Renderer-Klasse

Der erste Schritt zum Erstellen einer Renderer-Klasse besteht darin, Attribute und Methoden durch Erweitern einer Framework-Klasse höherer Ordnung zu erben.

Wir möchten Aufgaben nur durch ihre Start- und Endzeitdimensionen darstellen. Die ScheduleJS-Basis-Renderer-Klasse hierfür ist die Klasse ActivityBarRenderer.

Wir müssen die benutzerdefinierten Typargumente für die Klasse ActivityBarRenderer bereitstellen, damit auf die Attribute und Methoden unserer benutzerdefinierten Klassen Row und Activity zugegriffen werden kann unter Verwendung der Basisklassen-API.

Lassen Sie uns die Klasse ScheduleJsViewerTaskActivityRenderer erstellen, um jede ScheduleJsViewerTaskActivity in ihrer jeweiligen ScheduleJsViewerTaskRow zu zeichnen.

// 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 { }

So wie es ist, kann der Renderer bereits registriert werden, um unsere Aktivitäten mit dem Standardverhalten des ActivityBarRenderer zu zeichnen. Lassen Sie uns nun näher darauf eingehen, wie Sie es anpassen können.

Die Basisarchitektur

In ScheduleJS ist ein ActivityRenderer eine Klasse, die wir programmgesteuert mithilfe der Grafik-API registrieren, um eine bestimmte Aktivität in ihrer Zeile zu zeichnen. Um unseren ScheduleJsViewerTaskActivityRenderer zu organisieren, werden wir seinen Code in drei Abschnitte unterteilen:

  • Die Attribute enthalten Variablen, mit denen wir das Verhalten für einen bestimmten Zeichenvorgang ändern können.
  • Mit dem Konstruktor können wir einen Standardstatus für den Renderer definieren.
  • Die Zeichenmethoden enthalten alle Anweisungen zum Zeichnen unserer Aktivitäten auf der Leinwand.

Attribute

Attribute sind Konstanten, die im gesamten Renderer wiederverwendet werden. So wie sie sind, werden diese Eigenschaften nur direkt im Renderer-Code bearbeitet. Wir können uns einen bestimmten Bildschirm vorstellen, auf dem der Benutzer diese Einstellungen direkt in der Benutzeroberfläche ändern kann.

// 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;

Konstrukteur

Der Konstruktor ist eng mit unserer Renderer-Lebenszyklusmethode verknüpft. Im ScheduleJS Viewer haben wir beschlossen, den Renderer immer dann zu instanziieren, wenn der Benutzer den Bildschirm wechselt, um Besonderheiten zu definieren und unseren Code in jeder Registerkarte wiederzuverwenden, die diesen Renderer implementiert. Dies bedeutet, dass die Konstruktorfunktion jedes Mal ausgeführt wird, wenn der Benutzer einen Bildschirm mit diesem Renderer auswählt.

// 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 und setBarHeight werden geerbt und verwendet, um die Standard-Rendering-Eigenschaften der ActivityBarRenderer-Klasse zu ändern.

Die Standardfunktionen dieses Renderers sind die folgenden:

  • Eine benutzerdefinierte Farbe beim Bewegen der Maus über Aktivitäten
  • Ein schwarzer Strich (für Aktivitätsgrenzen)
  • Eine Strichlinienstärke von 0,5 Pixel
  • Eine Aktivitätsleistenhöhe von 8 Pixeln
  • Eine bedingte Füllfarbe: Blau für Kinder und Braun für Eltern im WBS-Tab Grün für Kinder und Grau für Eltern in den anderen Registerkarten

Zeichnung

Das Framework ruft automatisch die Methode drawActivity auf, um unsere Aktivitäten auf der Leinwand darzustellen. Alle Parameter werden dynamisch gefüllt, sodass Sie in Echtzeit auf den aktuellen Stand Ihrer Aktivitäten reagieren können.

// 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);
  }

Die Zeichnung erfolgt folgendermaßen:

  • Informationen zur aktuellen Aktivität und zur Zeile mithilfe der ActivityRef-API erhalten
  • Farben dynamisch mit unserer _setActivityColor-Methode festlegen
  • Zeichnen Sie Aktivitätstext mit unserer _drawActivityText-Methode
  • Zeichnen Sie die Aktivität selbst basierend auf zwei Methoden: Die _drawParentActivity-Methode zum Zeichnen von Eltern Die super.drawActivity-Standardmethode ActivityBarRenderer zum Zeichnen von untergeordneten Elementen

Benutzerdefinierte Methoden zum Zeichnen von Aktivitäten

Sehen wir uns genauer an, wie Sie Ihre Aktivität frei zeichnen können, indem Sie Ihre eigenen Methoden mit der _drawParentActivity-Methode entwerfen.

// 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);
  }

Hier verwenden wir direkt die HTMLCanvas-API, um unsere Zeichenstrategie zu definieren, indem wir den CanvasRenderingContex2D einrichten. Der einzige Framework-bezogene Vorgang, der in dieser Methode durchgeführt wird, ist das Erstellen einiger neuer ActivityBounds für die aktuelle übergeordnete Activity.

Das Framework erstellt eine Karte mit ActivityBounds unter der Haube, um alle Aktivitäten auf dem Bildschirm zu registrieren. Diese Karte hilft dem Entwickler, indem sie eine elementartige Logik bereitstellt, um erweiterte Benutzererlebnisse auf der Grundlage genauer Informationen zu erstellen und gleichzeitig die Leistung der HTMLCanvas-API zu nutzen.

Die Methoden zum Zeichnen von Elementen wie _drawParentActivityStartTriangle basieren auf der CanvasRenderingContext2D-API, um auf Pixelebene zu zeichnen.

// 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();
}

Endergebnis

Um Ihren brandneuen Renderer zu registrieren, verwenden Sie die Graphics.setActivityRenderer-Methode:

// Register the renderer

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

brand-new renderer

Um das Video des Endergebnisses zu sehen, gehen Sie zu: Erstellen eines ActivityRenderer

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/lenormor/building-an-activityrenderer-3o0?1 Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3