@byomakase/omakase-player
Version:
## Omakase Player - Open source JavaScript framework for building frame accurate video experiences
262 lines (261 loc) • 10.5 kB
TypeScript
import Konva from 'konva';
import { ScrollableHorizontally } from './scrollbar/scrollbar';
import { Dimension, Horizontals, Position, RectMeasurement } from '../common';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { Destroyable, PlayheadMoveEvent, ScrubberMoveEvent, TimecodeClickEvent, TimecodeMouseMoveEvent, TimelineReadyEvent, TimelineScrollEvent, TimelineZoomEvent } from '../types';
import { ScrubberLane } from './scrubber';
import { TimelineApi, TimelineLaneApi } from '../api';
import { AxiosRequestConfig } from 'axios';
import { PlaybackState, VideoControllerApi } from '../video';
import { FlexNode } from '../layout/flex-node';
import { ThumbnailVttFile } from '../vtt';
import { ConfigWithOptionalStyle } from '../layout';
export interface TimelineStyle {
textFontFamily: string;
textFontStyle: string;
stageMinWidth: number;
stageMinHeight: number;
backgroundFill: string;
backgroundOpacity: number;
headerHeight: number;
headerMarginBottom: number;
headerBackgroundFill: string;
headerBackgroundOpacity: number;
footerHeight: number;
footerMarginTop: number;
footerBackgroundFill: string;
footerBackgroundOpacity: number;
scrollbarHeight: number;
scrollbarWidth: number;
scrollbarBackgroundFill: string;
scrollbarBackgroundFillOpacity: number;
scrollbarHandleBarFill: string;
scrollbarHandleBarOpacity: number;
scrollbarHandleOpacity: number;
thumbnailHoverWidth: number;
thumbnailHoverStroke: string;
thumbnailHoverStrokeWidth: number;
thumbnailHoverYOffset: number;
leftPaneWidth: number;
rightPaneMarginLeft: number;
rightPaneMarginRight: number;
rightPaneClipPadding: number;
playheadVisible: boolean;
playheadFill: string;
playheadLineWidth: number;
playheadSymbolHeight: number;
playheadScrubberHeight: number;
playheadBackgroundFill: string;
playheadBackgroundOpacity: number;
playheadTextFill: string;
playheadTextYOffset: number;
playheadTextFontSize: number;
playheadPlayProgressFill: string;
playheadPlayProgressOpacity: number;
playheadBufferedFill: string;
playheadBufferedOpacity: number;
scrubberVisible: boolean;
scrubberFill: string;
scrubberSnappedFill: string;
scrubberNorthLineWidth: number;
scrubberNorthLineOpacity: number;
scrubberSouthLineWidth: number;
scrubberSouthLineOpacity: number;
scrubberSymbolHeight: number;
scrubberTextFill: string;
scrubberTextYOffset: number;
scrubberTextFontSize: number;
scrubberHeight: number;
scrubberMarginBottom: number;
loadingAnimationTheme: 'light' | 'dark';
}
export interface TimelineConfig {
timelineHTMLElementId: string;
thumbnailVttUrl?: string;
thumbnailVttFile?: ThumbnailVttFile;
axiosConfig?: AxiosRequestConfig;
scrubberSnapArea: number;
playheadDragScrollMaxSpeedAfterPx: number;
zoomWheelEnabled: boolean;
zoomScale: number;
zoomScaleWheel: number;
zoomBaseline: number;
zoomMax: number;
layoutEasingDuration: number;
zoomEasingDuration: number;
scrollEasingDuration: number;
scrubberClickSeek: boolean;
timecodeClickEdit: boolean;
style: TimelineStyle;
}
interface DragConditions {
positionBeforeDrag: Position | undefined;
playbackState: PlaybackState | undefined;
isPlayheadDrag: boolean;
}
export declare class Timeline implements Destroyable, ScrollableHorizontally, TimelineApi {
readonly onReady$: BehaviorSubject<TimelineReadyEvent | undefined>;
readonly onScroll$: Subject<TimelineScrollEvent>;
readonly onZoom$: Subject<TimelineZoomEvent>;
readonly onStyleChange$: Subject<TimelineStyle>;
readonly onTimecodeClick$: Subject<TimecodeClickEvent>;
readonly onTimecodeMouseMove$: Subject<TimecodeMouseMoveEvent>;
readonly onScrubberMove$: Subject<ScrubberMoveEvent>;
readonly onPlayheadMove$: Subject<PlayheadMoveEvent>;
protected _dragBreaker$: Subject<void>;
protected _dragConditions?: DragConditions;
private _config;
private _styleAdapter;
private readonly _vttAdapter;
private _videoController;
private _timelineDomController;
private _timelineLanes;
private _timelineLanesMap;
private _konvaStage;
private _mainLayer;
private _timecodedContainer;
private _timecodedFloatingGroup;
private _timecodedFloatingBg;
private _timecodedFloatingEventCatcher;
private _timecodedFloatingContentGroups;
private _surfaceLayer;
private _surfaceLayer_timecodedContainer;
private _surfaceLayer_timecodedFloatingGroup;
private _surfaceLayer_timecodedFloatingContentGroups;
private _layoutBg;
private _headerBg;
private _footerBg;
private _layoutFlexGroup;
private _headerFlexGroup;
private _mainFlexGroup;
private _mainLeftFlexGroup;
private _mainRightFlexGroup;
private _timelineLaneStaticFlexGroup;
private _timecodedWrapperFlexGroup;
private _timecodedContainerFlexGroup;
private _timecodedContainerStaticFlexGroup;
private _footerFlexGroup;
private _scrubber;
private _playhead;
private _scrubberLane;
private _thumbnailHover;
private _scrollWithPlayhead;
private _syncTimelineWithPlayheadInProgress;
private _descriptionPaneVisible;
private _videoEventBreaker$;
private readonly _destroyed$;
constructor(config: Partial<ConfigWithOptionalStyle<TimelineConfig>>, videoController: VideoControllerApi);
protected init(): void;
private handleTimecodeClick;
settleLayout(): void;
private settleTimecodedGroups;
private layersSync;
private onWindowResize;
private resolveStageDimension;
private showThumbnailHover;
private hideThumbnailHover;
private resolveThumbnailPosition;
private createScrollEvent;
private createZoomEvent;
getHorizontalScrollPercent(): number;
scrollHorizontallyToPercent(percent: number): void;
getScrollHandleHorizontals(scrollbarWidth: number): Horizontals;
scrollToEased(percent: number): Observable<number>;
scrollToPlayheadEased(): Observable<number>;
private scrollToPercent;
private scrollToPercentEased;
private scrollToPositionEased;
private isPlayheadInTimecodedView;
private refreshScrollWithPlayhead;
/**
* Scrolls timecoded group so that playhead is at left most position
* @private
*/
private syncTimelineWithPlayhead;
scrollTimeline(x: number): void;
private calculateTimelineXFromScrollPercent;
getZoomPercent(): number;
zoomTo(percent: number, zoomFocusPercent?: number | undefined): number;
zoomToEased(percent: number, zoomFocusPercent?: number | undefined): Observable<number>;
private resolveTimecodedFloatingPosition;
zoomInEased(): Observable<number>;
zoomOutEased(): Observable<number>;
zoomToMaxEased(): Observable<number>;
private zoomByStep;
private zoomByPercent;
private zoomByWidth;
private settleTimecodedFloating;
private zoomByStepEased;
private zoomByPercentEased;
private zoomByWidthEased;
private resolveTimelineContainerZoomFocusPosition;
private calculateTimecodedWidthFromZoomRatioPercent;
private getConstrainedTimecodedWidth;
private getConstrainedZoomPercent;
private getConstrainedScrollPercent;
private scrubberMove;
private onVideoLoadedEvent;
private fireVideoEventBreaker;
private syncVideoMetadata;
addTimelineLane(timelineLane: TimelineLaneApi): TimelineLaneApi;
private _addTimelineLane;
addTimelineLaneAtIndex(timelineLane: TimelineLaneApi, index: number): TimelineLaneApi;
private _addTimelineLaneAtIndex;
removeTimelineLane(id: string): void;
removeTimelineLanes(ids: string[]): void;
removeAllTimelineLanes(): void;
private _removeTimelineLane;
addTimelineLanes(timelineLanes: TimelineLaneApi[]): TimelineLaneApi[];
getTimelineLanes(): TimelineLaneApi[];
getTimelineLane<T extends TimelineLaneApi>(id: string): T | undefined;
getScrubberLane(): ScrubberLane;
addToTimecodedFloatingContent(node: Konva.Group | Konva.Shape, zIndex?: number): void;
addToTimecodedStaticContent(node: Konva.Group | Konva.Shape, zIndex?: number): void;
addToSurfaceLayerTimecodedFloatingContent(node: Konva.Group | Konva.Shape, zIndex?: number): void;
addToFooterFlexGroup(flexNode: FlexNode<any>): void;
constrainTimelinePosition(x: number): number;
timelinePositionToTime(xOnTimeline: number): number;
timelineContainerPositionToTime(xOnTimeline: number): number;
timelinePositionToTimecode(x: number): string;
timelinePositionToFrame(x: number): number;
timeToTimelinePosition(time: number): number;
private convertTimeToTimelinePosition;
private convertPositionOnTimelineToTime;
private constrainTimecodedFloatingPosition;
getTimecodedContainerDimension(): Dimension;
getTimecodedFloatingDimension(): Dimension;
getTimecodedFloatingPosition(): Position;
getTimecodedFloatingRelativePointerPosition(): Position | undefined;
getTimecodedFloatingRect(): RectMeasurement;
getTimecodedFloatingHorizontals(): Horizontals;
getVisiblePositionRange(): {
start: number;
end: number;
};
private isInVisiblePositionRange;
private isSnappedStart;
private isSnappedEnd;
getVisibleTimeRange(): {
start: number;
end: number;
};
loadThumbnailVttFile(vttFile: ThumbnailVttFile): void;
loadThumbnailVttFileFromUrl(vttUrl: string): Observable<ThumbnailVttFile | undefined>;
setDescriptionPaneVisible(visible: boolean): void;
toggleDescriptionPaneVisible(): void;
setDescriptionPaneVisibleEased(visible: boolean): Observable<void>;
toggleDescriptionPaneVisibleEased(): Observable<void>;
protected _minimizeTimelineLane(timelineLane: TimelineLaneApi, refreshLayout?: boolean): void;
minimizeTimelineLanes(timelineLanes: TimelineLaneApi[]): void;
protected _maximizeTimelineLane(timelineLane: TimelineLaneApi, refreshLayout?: boolean): void;
maximizeTimelineLanes(timelineLanes: TimelineLaneApi[]): void;
get thumbnailVttFile(): ThumbnailVttFile | undefined;
get style(): TimelineStyle;
set style(value: Partial<TimelineStyle>);
private clearContent;
get config(): TimelineConfig;
get descriptionPaneVisible(): boolean;
toggleTimecodeEdit(): void;
destroy(): void;
}
export {};