Cet article montre comment mettre en œuvre un rendu dynamique en fonction du niveau de zoom actuel des graphiques.
Le moteur de rendu de l'activité Gantt est le moteur de rendu principal du ScheduleJS Viewer. Cet article explique comment il est construit et quelles sont les spécificités de ce moteur de rendu d'activité.
La première étape de la construction d'une classe de moteur de rendu consiste à hériter des attributs et des méthodes en étendant une classe de cadre d'ordre supérieur.
Nous voulons représenter les tâches uniquement par leurs heures de début et de fin. La classe de rendu de base de ScheduleJS pour ce faire est la classe ActivityBarRenderer classe.
Nous devons fournir les arguments de type personnalisé à la fonction ActivityBarRenderer de sorte que les attributs et les méthodes fournis par notre classe de Row et un projet Activity seront accessibles à l'aide de l'API de la classe de base.
Créons le ScheduleJsViewerTaskActivityRenderer pour dessiner chaque ScheduleJsViewerTaskActivity dans leur respectif 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> { }
Tel quel, le moteur de rendu peut déjà être enregistré pour dessiner nos activités en utilisant le comportement par défaut de la méthode ActivityBarRenderer. Voyons maintenant comment le personnaliser.
Dans ScheduleJS, un ActivityRenderer est une classe que nous enregistrons par programme à l'aide de la fonction Graphics API pour dessiner un Activity on its 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 le moteur de rendu. En l'état, ces propriétés ne seront modifiées que directement dans le code du moteur de rendu. Nous pouvons imaginer un écran spécifique où l'utilisateur pourrait modifier ces paramètres directement dans l'interface utilisateur.
// 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 lié à 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 afin de définir des spécificités et de 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 utilisant 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;
}
}
Le setFill
, setStroke
, setFillHover
, setStrokeHover
, setLineWidth,
et un projet setBarHeight
sont héritées et utilisées pour modifier les caractéristiques de rendu par défaut de l'élément ActivityBarRenderer classe.
The default features of this renderer are the following:
Le cadre appellera automatiquement la fonction drawActivity
pour rendre nos activités sur le canevas. Tous ses paramètres sont remplis dynamiquement, ce qui vous permet 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 dessin se fera de cette manière :
_setActivityColor
method_drawActivityText
method_drawParentActivity
pour dessiner les parentssuper.drawActivity
par default ActivityBarRenderer pour dessiner les enfantsRegardons de plus près comment dessiner librement votre activité en concevant vos propres méthodes à l'aide de la méthode _drawParentActivity
methode.
// 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 la fonction HTMLCanvas API de définir notre stratégie de dessin en mettant en place le CanvasRenderingContex2D. La seule opération liée au cadre effectuée dans cette méthode consiste à créer de nouvelles ActivityBounds pour le parent actuel Activity.
Le cadre crée une carte à l'aide de ActivityBounds sous le capot pour enregistrer toutes les activités à l'écran. Cette carte aide le développeur en lui fournissant une logique semblable à celle d'un élément pour construire des expériences utilisateur avancées basées sur des informations précises tout en tirant parti de la performance de HTMLCanvas API.
Les méthodes des éléments de dessin comme _drawParentActivityStartTriangle
s'appuyer sur la CanvasRenderingContext2D API pour dessiner au niveau du pixel.
// 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();
}
Pour enregistrer votre nouveau moteur de rendu, utilisez la fonction graphics.setActivityRenderer
methode:
// Register the renderer
graphics.setActivityRenderer(ScheduleJsViewerTaskActivity, GanttLayout, new ScheduleJsViewerTaskActivityRenderer(graphics, currentRibbonMenuTab));
Cet article montre comment mettre en œuvre un rendu dynamique en fonction du niveau de zoom actuel des graphiques.
Cet article vous montrera comment a été construite l'architecture de l'arbre de Gantt parent-enfant dans le ScheduleJS Viewer.
Cet article montre comment le moteur de rendu de l'activité principale du ScheduleJS Viewer a été construit à l'aide d'exemples de code.
Cet article présente les principales fonctionnalités du ScheduleJS Viewer. Une toute nouvelle visionneuse de projets basée sur le web.
I particularly liked the way you explained how to build the renderer. The explanations on creating classes and managing drawing methods are very clear.”