El procesador de actividades de Gantt es el procesador principal de ScheduleJS Viewer. Este artículo analizará cómo está construido y cuáles son las especificidades de este renderizador de actividades.
El primer paso para construir una clase de renderizador es heredar atributos y métodos extendiendo una clase marco de orden superior.
Queremos representar las tareas solo a través de sus dimensiones de tiempo de inicio y finalización. La clase de renderizador base de ScheduleJS para hacer esto es la clase ActivityBarRenderer.
Necesitamos proporcionar argumentos de tipo personalizado a la clase ActivityBarRenderer para que los atributos y métodos proporcionados por nuestras clases personalizadas Row y Activity sean accesibles. usando la API de clase base.
Creemos la clase ScheduleJsViewerTaskActivityRenderer para dibujar cada ScheduleJsViewerTaskActivity en su respectiva 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{ }
Tal como está, el renderizador ya se puede registrar para dibujar nuestras actividades usando el comportamiento predeterminado de ActivityBarRenderer. Ahora profundicemos en cómo personalizarlo.
En ScheduleJS, un ActivityRenderer es una clase que registramos mediante programación usando la API de gráficos para dibujar una Actividad específica en su Fila. Para organizar nuestro ScheduleJsViewerTaskActivityRenderer, separaremos su código en tres secciones:
Los atributos son constantes que se reutilizarán en todo el renderizador. Tal como están, estas propiedades solo se editarán directamente en el código del renderizador. Podemos imaginar una pantalla específica donde el usuario podría modificar estas configuraciones directamente en la 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;
El constructor está estrechamente acoplado a nuestro método de ciclo de vida del renderizador. En ScheduleJS Viewer, decidimos crear una instancia del renderizador cada vez que el usuario cambia de pantalla para definir especificidades y reutilizar nuestro código en cada pestaña que implemente este renderizador. Significa que la función constructora se ejecuta cada vez que el usuario selecciona una pantalla que presenta este renderizador.
// 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 y setBarHeight se heredan y se utilizan para alterar las características de representación predeterminadas de la clase ActivityBarRenderer.
Las características predeterminadas de este renderizador son las siguientes:
El marco llamará automáticamente al método drawActivity para representar nuestras actividades en el lienzo. Todos sus parámetros se completan dinámicamente, lo que le permite reaccionar en tiempo real al estado actual de sus actividades.
// 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); }
El sorteo se realizará de esta manera:
Echemos un vistazo más de cerca a cómo dibujar libremente su actividad diseñando sus propios métodos con el método _drawParentActivity.
// 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); }
Aquí utilizamos directamente la HTMLCanvas API para definir nuestra estrategia de dibujo configurando CanvasRenderingContex2D. La única operación relacionada con el marco realizada en este método es crear algunos ActivityBounds nuevos para la Activity principal actual.
El marco crea un mapa usando ActivityBounds debajo del capó para registrar todas las actividades en la pantalla. Este mapa ayuda al desarrollador al proporcionar una lógica similar a un elemento para crear experiencias de usuario avanzadas basadas en información precisa y, al mismo tiempo, aprovechar el rendimiento de la HTMLCanvas API.
Los métodos de dibujo de elementos como _drawParentActivityStartTriangle dependen de la API CanvasRenderingContext2D para dibujar a nivel de píxel.
// 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(); }
Para registrar su nuevo renderizador, utilice el método Graphics.setActivityRenderer:
// Register the renderer graphics.setActivityRenderer(ScheduleJsViewerTaskActivity, GanttLayout, new ScheduleJsViewerTaskActivityRenderer(graphics, currentRibbonMenuTab));
Para ver el vídeo del resultado final puedes ir a ver: Construyendo un ActivityRenderer
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3