scroll-seamless
Version:
A seamless scroll library for JS, Vue, and React.
713 lines (702 loc) • 17.2 kB
TypeScript
type ScrollDirection = 'up' | 'down' | 'left' | 'right';
type ScrollSeamlessEvent =
| 'start'
| 'stop'
| 'destroy'
| 'update'
| 'reach-end'
| 'reach-start';
interface PerformancePluginOptions {
enabled?: boolean;
fps?: boolean;
memory?: boolean;
timing?: boolean;
onUpdate?: (metrics: any) => void;
}
interface AccessibilityPluginOptions {
enabled?: boolean;
ariaLabel?: string;
keyboardNavigation?: boolean;
screenReader?: boolean;
focusable?: boolean;
}
interface ScrollSeamlessPlugin {
id: string;
apply: (instance: ScrollSeamlessController) => void;
destroy?: () => void;
}
interface ScrollSeamlessOptions {
data: string[];
direction?: ScrollDirection;
minCountToScroll?: number;
step?: number;
stepWait?: number;
delay?: number;
bezier?: [number, number, number, number];
hoverStop?: boolean;
wheelEnable?: boolean;
singleLine?: boolean;
rows?: number;
cols?: number;
onEvent?: (event: ScrollSeamlessEvent, data?: any) => void;
plugins?: ScrollSeamlessPlugin[];
performance?: PerformancePluginOptions;
accessibility?: AccessibilityPluginOptions;
}
interface ScrollSeamlessController {
start: () => void;
stop: () => void;
destroy: () => void;
updateData: () => void;
setOptions: (options: Partial<ScrollSeamlessOptions>) => void;
isRunning: () => boolean;
getPosition?: () => number;
setPosition?: (position: number) => void;
addPlugin?: (plugin: ScrollSeamlessPlugin) => void;
removePlugin?: (pluginId: string) => void;
getPerformance?: () => any;
}
/**
* 扩展选项接口,添加 renderItem
*/
interface ExtendedScrollSeamlessOptions extends ScrollSeamlessOptions {
renderItem?: (item: string, index: number, rowIndex?: number, colIndex?: number) => HTMLElement;
}
/**
* 滚动引擎类 - 重构后的核心实现
* 提供更好的可扩展性、健壮性和性能
*/
declare class ScrollEngine implements ScrollSeamlessController {
private container;
private options;
private memoryManager;
private domCache;
private elementPool;
private pluginManager;
private running;
private rowStates;
private colStates;
private seamlessData;
private seamlessColData;
constructor(container: HTMLElement | null, options: ExtendedScrollSeamlessOptions);
/**
* 合并默认选项和用户选项
*/
private mergeOptions;
/**
* 初始化滚动引擎
*/
private initialize;
/**
* 设置容器样式
*/
private setupContainer;
/**
* 创建滚动元素
*/
private createScrollElements;
/**
* 创建水平滚动元素
*/
private createHorizontalElements;
/**
* 创建垂直滚动元素
*/
private createVerticalElements;
/**
* 创建元素的辅助方法
*/
private createElement;
/**
* 设置元素样式的辅助方法
*/
private setElementStyle;
/**
* 设置内容样式
*/
private setContentStyle;
/**
* 绑定事件
*/
private bindEvents;
/**
* 布局计算
*/
private layout;
/**
* 水平布局计算
*/
private layoutHorizontal;
/**
* 垂直布局计算
*/
private layoutVertical;
/**
* 计算无缝滚动所需的项目
*/
private calculateSeamlessItems;
/**
* 渲染内容
*/
private renderContent;
/**
* 渲染水平内容
*/
private renderHorizontalContent;
/**
* 渲染垂直内容
*/
private renderVerticalContent;
/**
* 渲染状态内容
*/
private renderStateContent;
/**
* 判断是否应该滚动
*/
private shouldScroll;
/**
* 开始滚动
*/
start(): void;
/**
* 创建滚动动画
*/
private createScrollAnimation;
/**
* 停止滚动
*/
stop(): void;
/**
* 销毁实例
*/
destroy(): void;
/**
* 更新数据并重新布局
*/
updateData(): void;
/**
* 设置选项
*/
setOptions(options: Partial<ExtendedScrollSeamlessOptions>): void;
/**
* 获取运行状态
*/
isRunning(): boolean;
/**
* 获取渲染矩阵(用于数据驱动模式)
*/
getRenderMatrix(): string[][];
/**
* 获取变换样式(用于数据驱动模式)
*/
getTransforms(): string[];
/**
* 添加插件
* @param plugin 插件实例
*/
addPlugin(plugin: ScrollSeamlessPlugin): void;
/**
* 移除插件
* @param pluginId 插件ID
*/
removePlugin(pluginId: string): void;
/**
* 获取当前位置
* @returns 当前位置
*/
getPosition(): number;
/**
* 设置当前位置
* @param position 位置
*/
setPosition(position: number): void;
/**
* 获取性能数据
* @returns 性能数据
*/
getPerformance(): any;
/**
* 事件处理器
*/
private onMouseEnter;
private onMouseLeave;
private onWheel;
/**
* 错误处理
*/
private handleError;
}
/**
* 通用对象池实现,用于复用对象以减少垃圾回收
*/
declare class ObjectPool<T> {
private pool;
private factory;
private reset;
private maxSize;
private created;
constructor(factory: () => T, reset: (item: T) => void, initialSize?: number, maxSize?: number);
/**
* 从池中获取对象
*/
acquire(): T;
/**
* 将对象归还到池中
*/
release(item: T): void;
/**
* 清空池
*/
clear(): void;
/**
* 获取池状态
*/
getStats(): {
poolSize: number;
totalCreated: number;
maxSize: number;
};
}
/**
* DOM元素对象池
*/
declare class DOMElementPool {
private spanPool;
private divPool;
constructor();
acquireSpan(): HTMLSpanElement;
releaseSpan(span: HTMLSpanElement): void;
acquireDiv(): HTMLDivElement;
releaseDiv(div: HTMLDivElement): void;
clear(): void;
}
/**
* 动画接口定义
*/
interface Animation {
id: string;
callback: (timestamp: number) => boolean;
priority: number;
startTime?: number;
lastFrameTime?: number;
}
/**
* 性能监控接口
*/
interface PerformanceMetrics$1 {
fps: number;
frameTime: number;
droppedFrames: number;
activeAnimations: number;
}
/**
* 统一的requestAnimationFrame调度器
* 解决多实例时的动画性能问题
*/
declare class RAFScheduler {
private static instance;
private animations;
private isRunning;
private rafId;
private lastTimestamp;
private frameCount;
private droppedFrames;
private fpsHistory;
private maxFPSHistory;
private frameTimeThreshold;
private constructor();
/**
* 获取单例实例
*/
static getInstance(): RAFScheduler;
/**
* 添加动画到调度队列
*/
schedule(animation: Animation): void;
/**
* 移除动画
*/
unschedule(animationId: string): void;
/**
* 暂停特定动画
*/
pause(animationId: string): void;
/**
* 恢复特定动画
*/
resume(animationId: string): void;
/**
* 暂停所有动画
*/
pauseAll(): void;
/**
* 恢复所有动画
*/
resumeAll(): void;
/**
* 开始调度循环
*/
private start;
/**
* 停止调度循环
*/
private stop;
/**
* 主要的动画循环
*/
private tick;
/**
* 更新FPS统计
*/
private updateFPS;
/**
* 获取当前性能指标
*/
getPerformanceMetrics(): PerformanceMetrics$1;
/**
* 获取调度器状态
*/
getStatus(): {
fps: number;
frameTime: number;
droppedFrames: number;
activeAnimations: number;
isRunning: boolean;
frameCount: number;
};
/**
* 重置性能统计
*/
resetStats(): void;
/**
* 销毁调度器
*/
destroy(): void;
}
/**
* 动画辅助函数
*/
declare class AnimationHelper {
private static idCounter;
/**
* 生成唯一动画ID
*/
static generateId(prefix?: string): string;
/**
* 创建简单的位移动画
*/
static createTransformAnimation(element: HTMLElement, from: {
x: number;
y: number;
}, to: {
x: number;
y: number;
}, duration: number, easing?: (t: number) => number): Animation;
/**
* 创建无限滚动动画
*/
static createScrollAnimation(element: HTMLElement, direction: 'left' | 'right' | 'up' | 'down', speed: number, contentSize: number): Animation;
}
declare const rafScheduler: RAFScheduler;
/**
* 内存管理器 - 负责资源清理和内存泄漏防护
*/
declare class MemoryManager {
private cleanupTasks;
private eventListeners;
private observers;
private timers;
private intervals;
private rafIds;
private isDestroyed;
/**
* 添加清理任务
*/
addCleanupTask(task: () => void): void;
/**
* 安全的事件监听器添加
*/
addEventListener(element: HTMLElement, event: string, listener: EventListener, options?: AddEventListenerOptions): void;
/**
* 移除事件监听器
*/
removeEventListener(element: HTMLElement, event: string, listener: EventListener): void;
/**
* 创建并管理 MutationObserver
*/
createMutationObserver(callback: MutationCallback, target: Node, options?: MutationObserverInit): MutationObserver;
/**
* 管理定时器
*/
setTimeout(callback: () => void, delay: number): number;
setInterval(callback: () => void, delay: number): number;
clearTimeout(id: number): void;
clearInterval(id: number): void;
/**
* 管理 requestAnimationFrame
*/
requestAnimationFrame(callback: FrameRequestCallback): number;
cancelAnimationFrame(id: number): void;
/**
* 获取内存使用统计
*/
getMemoryStats(): {
cleanupTasks: number;
eventListeners: number;
observers: number;
timers: number;
intervals: number;
rafIds: number;
isDestroyed: boolean;
};
/**
* 完全清理所有资源
*/
destroy(): void;
}
/**
* DOM测量结果接口
*/
interface ElementMeasurement {
width: number;
height: number;
offsetWidth: number;
offsetHeight: number;
scrollWidth: number;
scrollHeight: number;
timestamp: number;
}
/**
* DOM测量缓存管理器
*/
declare class DOMCache {
private measurementCache;
private textSizeCache;
private resizeObserver;
private observedElements;
private cacheTimeout;
constructor(cacheSize?: number);
/**
* 生成元素的唯一键
*/
private getElementKey;
/**
* 生成文本测量的键
*/
private getTextKey;
/**
* 实际测量元素
*/
private measureElement;
/**
* 获取元素测量结果(带缓存)
*/
getElementMeasurement(element: HTMLElement, forceRefresh?: boolean): ElementMeasurement;
/**
* 测量文本尺寸(带缓存)
*/
measureText(text: string, className?: string, styles?: Partial<CSSStyleDeclaration>): {
width: number;
height: number;
};
/**
* 批量测量文本
*/
measureTextBatch(texts: string[], className?: string, styles?: Partial<CSSStyleDeclaration>): {
width: number;
height: number;
}[];
/**
* 清除过期缓存
*/
clearExpiredCache(): void;
/**
* 获取缓存统计
*/
getCacheStats(): {
measurementCacheSize: number;
textCacheSize: number;
observedElements: string | number;
hasResizeObserver: boolean;
};
/**
* 销毁缓存
*/
destroy(): void;
}
/**
* 插件管理器类
* 负责管理和协调插件的生命周期
*/
declare class PluginManager {
private plugins;
private controller;
constructor(controller: ScrollSeamlessController);
/**
* 注册插件
* @param plugin 插件实例
*/
register(plugin: ScrollSeamlessPlugin): void;
/**
* 注销插件
* @param pluginId 插件ID
*/
unregister(pluginId: string): void;
/**
* 获取插件实例
* @param pluginId 插件ID
* @returns 插件实例或null
*/
getPlugin(pluginId: string): ScrollSeamlessPlugin | null;
/**
* 获取所有已注册的插件
* @returns 插件列表
*/
getPlugins(): ScrollSeamlessPlugin[];
/**
* 销毁所有插件
*/
destroyAll(): void;
}
/**
* 性能指标接口
*/
interface PerformanceMetrics {
fps: number;
memory: {
jsHeapSizeLimit: number;
totalJSHeapSize: number;
usedJSHeapSize: number;
} | null;
timing: {
renderTime: number;
animationTime: number;
};
elements: {
total: number;
visible: number;
};
}
/**
* 性能监控插件
* 用于监控滚动性能并提供性能指标
*/
declare class PerformancePlugin {
id: string;
private controller;
private options;
private metrics;
private monitoringInterval;
constructor(options?: PerformancePluginOptions);
/**
* 应用插件
* @param controller 滚动控制器
*/
apply(controller: ScrollSeamlessController): void;
/**
* 销毁插件
*/
destroy(): void;
/**
* 开始监控
*/
private startMonitoring;
/**
* 停止监控
*/
private stopMonitoring;
/**
* 更新性能指标
*/
private updateMetrics;
/**
* 获取性能指标
* @returns 性能指标
*/
getMetrics(): PerformanceMetrics;
}
/**
* 合法的滚动方向
*/
declare const legalDirections: readonly ["left", "right", "up", "down"];
/**
* 获取合法的滚动方向,如果不合法则返回默认值 'left'
* @param direction 滚动方向
* @returns 合法的滚动方向
*/
declare function getLegalDirection(direction: string): ScrollDirection;
/**
* 获取内容的变换样式
* @param direction 滚动方向
* @param position 当前位置
* @param totalLength 内容总长度
* @param isSecondContent 是否是第二个内容元素
* @returns 变换样式字符串
*/
declare function getContentTransform(direction: ScrollDirection, position: number, totalLength: number, isSecondContent: boolean): string;
/**
* 计算下一个位置
* @param direction 滚动方向
* @param position 当前位置
* @param step 步长
* @param totalLength 内容总长度
* @returns 下一个位置
*/
declare function getNextPosition(direction: ScrollDirection, position: number, step: number, totalLength: number): number;
/**
* 获取内容样式
* @param direction 滚动方向
* @returns CSS样式对象
*/
declare function getContentStyle(direction: ScrollDirection): Record<string, string | number>;
/**
* 触发事件
* @param handler 事件处理函数
* @param event 事件名称
* @param payload 事件数据
*/
declare function fireEvent(handler: ((event: string, payload?: any) => void) | undefined, event: string, payload?: any): void;
/**
* 获取渲染数据
* @param data 原始数据
* @param direction 滚动方向
* @returns 处理后的数据
*/
declare function getRenderData<T>(data: T[], direction: ScrollDirection): T[];
/**
* 防抖函数
* @param fn 要执行的函数
* @param delay 延迟时间
* @returns 防抖后的函数
*/
declare function debounce<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void;
/**
* 节流函数
* @param fn 要执行的函数
* @param limit 时间限制
* @returns 节流后的函数
*/
declare function throttle<T extends (...args: any[]) => any>(fn: T, limit: number): (...args: Parameters<T>) => void;
/**
* 检查浏览器支持的特性
* @returns 支持的特性对象
*/
declare function detectBrowserFeatures(): Record<string, boolean>;
/**
* 安全地执行DOM操作
* @param callback DOM操作回调
* @returns 操作结果
*/
declare function safeDOM<T>(callback: () => T): T | null;
declare const DEFAULT_OPTIONS: Required<Omit<ScrollSeamlessOptions, 'data'>>;
/**
* 创建无缝滚动实例
* @param container 容器元素
* @param options 配置选项
* @returns 滚动控制器
*/
declare function createScrollSeamless(container: HTMLElement, options: ScrollSeamlessOptions): ScrollSeamlessController;
declare const ScrollSeamless: typeof ScrollEngine;
export { AnimationHelper, DEFAULT_OPTIONS, DOMCache, DOMElementPool, MemoryManager, ObjectPool, PerformancePlugin, PluginManager, RAFScheduler, createScrollSeamless, debounce, ScrollSeamless as default, detectBrowserFeatures, fireEvent, getContentStyle, getContentTransform, getLegalDirection, getNextPosition, getRenderData, legalDirections, rafScheduler, safeDOM, throttle };
export type { Animation, ElementMeasurement, PerformanceMetrics$1 as PerformanceMetrics };