O renderizador de atividades Gantt é o renderizador principal do ScheduleJS Viewer. Este artigo irá discutir como ele é construído e quais são as especificidades deste renderizador de atividades.
A primeira etapa para construir uma classe renderizadora é herdar atributos e métodos estendendo uma classe de estrutura de ordem superior.
Queremos representar tarefas apenas por meio de suas dimensões de horário de início e término. A classe renderizadora base do ScheduleJS para fazer isso é a classe ActivityBarRenderer.
Precisamos fornecer os argumentos de tipo personalizado para a classe ActivityBarRenderer para que os atributos e métodos fornecidos por nossas classes personalizadas Row e Activity sejam acessíveis usando a API da classe base.
Vamos criar a classe ScheduleJsViewerTaskActivityRenderer para desenhar cada ScheduleJsViewerTaskActivity em seus respectivos 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{ }
No estado em que se encontra, o renderizador já pode ser registrado para desenhar nossas atividades usando o comportamento padrão do ActivityBarRenderer. Agora vamos ver como personalizá-lo.
No ScheduleJS, um ActivityRenderer é uma classe que registramos programaticamente usando a API Graphics para desenhar uma Activity específica em sua Row. Para organizar nosso ScheduleJsViewerTaskActivityRenderer, vamos separar seu código em três seções:
Atributos são constantes que serão reutilizadas em todo o renderizador. No estado em que se encontram, essas propriedades só serão editadas diretamente no código do renderizador. Podemos imaginar uma tela específica onde o usuário poderia modificar essas configurações diretamente na 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;
O construtor está fortemente acoplado ao nosso método de ciclo de vida do renderizador. No ScheduleJS Viewer, decidimos instanciar o renderizador sempre que o usuário troca de tela para definir especificidades e reaproveitar nosso código em todas as abas que implementam esse renderizador. Isso significa que a função construtora é executada toda vez que o usuário seleciona uma tela com 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 e setBarHeight são herdados e usados para alterar as características de renderização padrão da classe ActivityBarRenderer.
Os recursos padrão deste renderizador são os seguintes:
A estrutura chamará automaticamente o método drawActivity para renderizar nossas atividades na tela. Todos os seus parâmetros são preenchidos dinamicamente, permitindo reagir em tempo real ao estado atual de suas atividades.
// 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); }
O sorteio ocorrerá desta forma:
Vamos dar uma olhada mais de perto em como desenhar livremente sua atividade, projetando seus próprios métodos com o 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); }
Aqui usamos diretamente a HTMLCanvas API para definir nossa estratégia de desenho configurando o CanvasRenderingContex2D. A única operação relacionada à estrutura feita neste método é criar alguns novos ActivityBounds para o pai atual Activity.
A estrutura cria um mapa usando ActivityBounds nos bastidores para registrar todas as atividades na tela. Este mapa ajuda o desenvolvedor fornecendo uma lógica semelhante a um elemento para criar experiências de usuário avançadas com base em informações precisas e, ao mesmo tempo, aproveitar o desempenho da API HTMLCanvas.
Os métodos de elementos de desenho, como _drawParentActivityStartTriangle, dependem da API CanvasRenderingContext2D para desenhar no nível do 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(); }
Para registrar seu novo renderizador, use o método graphics.setActivityRenderer:
// Register the renderer graphics.setActivityRenderer(ScheduleJsViewerTaskActivity, GanttLayout, new ScheduleJsViewerTaskActivityRenderer(graphics, currentRibbonMenuTab));
Para ver o vídeo do resultado final você pode acessar: Construindo um ActivityRenderer
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3