Improves all-day event header animation performance
Optimizes all-day event header animation by caching DOM elements. This change avoids redundant DOM queries during animation, resulting in smoother transitions when adding or removing all-day events. It also introduces a destroy method for proper cleanup of cached elements.
This commit is contained in:
parent
7f387cfa30
commit
77592278d3
1 changed files with 81 additions and 12 deletions
|
|
@ -19,14 +19,76 @@ export interface HeaderRenderer {
|
|||
* Base class with shared addToAllDay implementation
|
||||
*/
|
||||
export abstract class BaseHeaderRenderer implements HeaderRenderer {
|
||||
// Cached DOM elements to avoid redundant queries
|
||||
private cachedCalendarHeader: HTMLElement | null = null;
|
||||
private cachedAllDayContainer: HTMLElement | null = null;
|
||||
private cachedHeaderSpacer: HTMLElement | null = null;
|
||||
|
||||
abstract render(calendarHeader: HTMLElement, context: HeaderRenderContext): void;
|
||||
|
||||
/**
|
||||
* Get cached calendar header element
|
||||
*/
|
||||
private getCalendarHeader(): HTMLElement | null {
|
||||
if (!this.cachedCalendarHeader) {
|
||||
this.cachedCalendarHeader = document.querySelector('swp-calendar-header');
|
||||
}
|
||||
return this.cachedCalendarHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached all-day container element
|
||||
*/
|
||||
private getAllDayContainer(): HTMLElement | null {
|
||||
if (!this.cachedAllDayContainer) {
|
||||
const calendarHeader = this.getCalendarHeader();
|
||||
if (calendarHeader) {
|
||||
this.cachedAllDayContainer = calendarHeader.querySelector('swp-allday-container');
|
||||
}
|
||||
}
|
||||
return this.cachedAllDayContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached header spacer element
|
||||
*/
|
||||
private getHeaderSpacer(): HTMLElement | null {
|
||||
if (!this.cachedHeaderSpacer) {
|
||||
this.cachedHeaderSpacer = document.querySelector('swp-header-spacer');
|
||||
}
|
||||
return this.cachedHeaderSpacer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate all-day height based on number of rows
|
||||
*/
|
||||
private calculateAllDayHeight(targetRows: number): {
|
||||
targetHeight: number;
|
||||
currentHeight: number;
|
||||
heightDifference: number;
|
||||
} {
|
||||
const root = document.documentElement;
|
||||
const targetHeight = targetRows * ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT;
|
||||
const currentHeight = parseInt(getComputedStyle(root).getPropertyValue('--all-day-row-height') || '0');
|
||||
const heightDifference = targetHeight - currentHeight;
|
||||
|
||||
return { targetHeight, currentHeight, heightDifference };
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached DOM elements (call when DOM structure changes)
|
||||
*/
|
||||
private clearCache(): void {
|
||||
this.cachedCalendarHeader = null;
|
||||
this.cachedAllDayContainer = null;
|
||||
this.cachedHeaderSpacer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand header to show all-day row
|
||||
*/
|
||||
addToAllDay(dayHeader: HTMLElement): void {
|
||||
const root = document.documentElement;
|
||||
const currentHeight = parseInt(getComputedStyle(root).getPropertyValue('--all-day-row-height') || '0');
|
||||
const { currentHeight } = this.calculateAllDayHeight(0);
|
||||
|
||||
if (currentHeight === 0) {
|
||||
// Find the calendar header element to animate
|
||||
|
|
@ -47,7 +109,7 @@ export abstract class BaseHeaderRenderer implements HeaderRenderer {
|
|||
}
|
||||
|
||||
checkAndAnimateAllDayHeight(): void {
|
||||
const container = document.querySelector('swp-allday-container');
|
||||
const container = this.getAllDayContainer();
|
||||
if (!container) return;
|
||||
|
||||
const allDayEvents = container.querySelectorAll('swp-allday-event');
|
||||
|
|
@ -100,24 +162,21 @@ export abstract class BaseHeaderRenderer implements HeaderRenderer {
|
|||
* Animate all-day container to specific number of rows
|
||||
*/
|
||||
animateToRows(targetRows: number): void {
|
||||
const root = document.documentElement;
|
||||
const targetHeight = targetRows * ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT;
|
||||
const currentHeight = parseInt(getComputedStyle(root).getPropertyValue('--all-day-row-height') || '0');
|
||||
const { targetHeight, currentHeight, heightDifference } = this.calculateAllDayHeight(targetRows);
|
||||
|
||||
if (targetHeight === currentHeight) return; // No animation needed
|
||||
|
||||
console.log(`🎬 All-day height animation starting: ${currentHeight}px → ${targetHeight}px (${Math.ceil(currentHeight / ALL_DAY_CONSTANTS.SINGLE_ROW_HEIGHT)} → ${targetRows} rows)`);
|
||||
|
||||
// Find elements to animate
|
||||
const calendarHeader = document.querySelector('swp-calendar-header') as HTMLElement;
|
||||
const headerSpacer = document.querySelector('swp-header-spacer') as HTMLElement;
|
||||
const allDayContainer = calendarHeader?.querySelector('swp-allday-container') as HTMLElement;
|
||||
// Get cached elements
|
||||
const calendarHeader = this.getCalendarHeader();
|
||||
const headerSpacer = this.getHeaderSpacer();
|
||||
const allDayContainer = this.getAllDayContainer();
|
||||
|
||||
if (!calendarHeader || !allDayContainer) return;
|
||||
|
||||
// Get current parent height for animation
|
||||
const currentParentHeight = parseFloat(getComputedStyle(calendarHeader).height);
|
||||
const heightDifference = targetHeight - currentHeight;
|
||||
const targetParentHeight = currentParentHeight + heightDifference;
|
||||
|
||||
const animations = [
|
||||
|
|
@ -133,6 +192,7 @@ export abstract class BaseHeaderRenderer implements HeaderRenderer {
|
|||
|
||||
// Add spacer animation if spacer exists
|
||||
if (headerSpacer) {
|
||||
const root = document.documentElement;
|
||||
const currentSpacerHeight = parseInt(getComputedStyle(root).getPropertyValue('--header-height')) + currentHeight;
|
||||
const targetSpacerHeight = parseInt(getComputedStyle(root).getPropertyValue('--header-height')) + targetHeight;
|
||||
|
||||
|
|
@ -150,6 +210,7 @@ export abstract class BaseHeaderRenderer implements HeaderRenderer {
|
|||
|
||||
// Update CSS variable after animation
|
||||
Promise.all(animations.map(anim => anim.finished)).then(() => {
|
||||
const root = document.documentElement;
|
||||
root.style.setProperty('--all-day-row-height', `${targetHeight}px`);
|
||||
eventBus.emit('header:height-changed');
|
||||
});
|
||||
|
|
@ -163,9 +224,17 @@ export abstract class BaseHeaderRenderer implements HeaderRenderer {
|
|||
// Create simple all-day container (initially hidden)
|
||||
container = document.createElement('swp-allday-container');
|
||||
calendarHeader.appendChild(container);
|
||||
} else {
|
||||
// Clear cache since DOM structure changed
|
||||
this.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public cleanup method for cached elements
|
||||
*/
|
||||
public destroy(): void {
|
||||
this.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue