Le moteur de rendu d'activité Gantt est le moteur de rendu principal de la visionneuse ScheduleJS. Cet article expliquera comment il est construit et quelles sont les spécificités de ce moteur de rendu d'activité.
La première étape pour créer une classe de rendu consiste à hériter des attributs et des méthodes en étendant une classe de framework d'ordre supérieur.
Nous souhaitons représenter les tâches uniquement à travers leurs dimensions temporelles de début et de fin. La classe de rendu de base ScheduleJS pour ce faire est la classe ActivityBarRenderer.
Nous devons fournir les arguments de type personnalisé à la classe ActivityBarRenderer afin que les attributs et méthodes fournis par nos classes personnalisées Row et Activity soient accessibles en utilisant l'API de la classe de base.
Créons la classe ScheduleJsViewerTaskActivityRenderer pour dessiner chaque ScheduleJsViewerTaskActivity dans leur 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<ScheduleJsViewerTaskActivity, ScheduleJsViewerTaskRow> { }
En l'état, le moteur de rendu peut déjà être enregistré pour dessiner nos activités en utilisant le comportement par défaut de ActivityBarRenderer. Voyons maintenant comment le personnaliser.
Dans ScheduleJS, un ActivityRenderer est une classe que nous enregistrons par programme à l'aide de l'API graphique pour dessiner une Activité spécifique sur sa Row. Pour organiser notre ScheduleJsViewerTaskActivityRenderer, nous allons séparer son code en trois sections :
Les attributs sont des constantes qui seront réutilisées dans tout le moteur de rendu. En l'état, ces propriétés ne seront modifiées que directement dans le code du moteur de rendu. On peut imaginer un écran spécifique où l'utilisateur pourrait modifier ces paramètres directement dans l'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;
Le constructeur est étroitement couplé à notre méthode de cycle de vie du moteur de rendu. Dans le ScheduleJS Viewer, nous avons décidé d'instancier le moteur de rendu à chaque fois que l'utilisateur change d'écran pour définir les spécificités et réutiliser notre code dans chaque onglet qui implémente ce moteur de rendu. Cela signifie que la fonction constructeur est exécutée chaque fois que l'utilisateur sélectionne un écran présentant ce moteur de rendu.
// 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; } }
Les setFill, setStroke, setFillHover, setStrokeHover, setLineWidth et setBarHeight sont hérités et utilisés pour modifier les caractéristiques de rendu par défaut de la classe ActivityBarRenderer.
Les fonctionnalités par défaut de ce moteur de rendu sont les suivantes :
Le framework appellera automatiquement la méthode drawActivity pour restituer nos activités sur le canevas. Tous ses paramètres sont renseignés dynamiquement, vous permettant de réagir en temps réel à l'état actuel de vos activités.
// 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); }
Le tirage se déroulera de cette façon :
Regardons de plus près comment dessiner librement votre activité en concevant vos propres méthodes avec la méthode _drawParentActivity.
// 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); }
Ici, nous utilisons directement l'API HTMLCanvas pour définir notre stratégie de dessin en mettant en place le CanvasRenderingContex2D. La seule opération liée au framework effectuée dans cette méthode consiste à créer de nouveaux ActivityBounds pour le parent actuel Activity.
Le framework crée une carte en utilisant ActivityBounds sous le capot pour enregistrer toutes les activités à l'écran. Cette carte aide le développeur en fournissant une logique de type élément pour créer des expériences utilisateur avancées basées sur des informations précises tout en tirant parti des performances de l'API HTMLCanvas.
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
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!