import * as React from "react"; import { observable, action, computed, runInAction, reaction, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; import "./TimelineOverview.scss"; import * as $ from 'jquery'; import { Timeline } from "./Timeline"; import { Keyframe, KeyframeFunc } from "./Keyframe"; interface TimelineOverviewProps { totalLength: number; visibleLength: number; visibleStart: number; currentBarX: number; isAuthoring: boolean; parent: Timeline; changeCurrentBarX: (pixel: number) => void; movePanX: (pixel: number) => any; time: number; tickSpacing: number; tickIncrement: number; } @observer export class TimelineOverview extends React.Component{ @observable private _visibleRef = React.createRef(); @observable private _scrubberRef = React.createRef(); @observable private authoringContainer = React.createRef(); @observable private playbackContainer = React.createRef(); @observable private overviewBarWidth: number = 0; @observable private playbarWidth: number = 0; @observable private activeOverviewWidth: number = 0; @observable private _authoringReaction?: IReactionDisposer; @observable private visibleTime: number = 0; @observable private currentX: number = 0; @observable private visibleStart: number = 0; private readonly DEFAULT_HEIGHT = 50; private readonly DEFAULT_WIDTH = 300; componentDidMount = () => { this.setOverviewWidth(); this._authoringReaction = reaction( () => this.props.parent._isAuthoring, () => { if (!this.props.parent._isAuthoring) { runInAction(() => { this.setOverviewWidth(); }); } }, ); } componentWillUnmount = () => { this._authoringReaction && this._authoringReaction(); } @action setOverviewWidth() { const width1 = this.authoringContainer.current?.clientWidth; const width2 = this.playbackContainer.current?.clientWidth; if (width1 && width1 !== 0) this.overviewBarWidth = width1; if (width2 && width2 !== 0) this.playbarWidth = width2; if (this.props.isAuthoring) { this.activeOverviewWidth = this.overviewBarWidth; } else { this.activeOverviewWidth = this.playbarWidth; } } @action onPointerDown = (e: React.PointerEvent) => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", this.onPanX); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPanX); document.addEventListener("pointerup", this.onPointerUp); } @action onPanX = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); const movX = (this.props.visibleStart / this.props.totalLength) * (this.DEFAULT_WIDTH) + e.movementX; this.props.movePanX((movX / (this.DEFAULT_WIDTH)) * this.props.totalLength); } @action onPointerUp = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", this.onPanX); document.removeEventListener("pointerup", this.onPointerUp); } @action onScrubberDown = (e: React.PointerEvent) => { e.preventDefault(); e.stopPropagation(); document.removeEventListener("pointermove", this.onScrubberMove); document.removeEventListener("pointerup", this.onScrubberUp); document.addEventListener("pointermove", this.onScrubberMove); document.addEventListener("pointerup", this.onScrubberUp); } @action onScrubberMove = (e: PointerEvent) => { e.preventDefault(); e.stopPropagation(); const scrubberRef = this._scrubberRef.current!; const left = scrubberRef.getBoundingClientRect().left; const offsetX = Math.round(e.clientX - left); this.props.changeCurrentBarX((((offsetX) / this.activeOverviewWidth) * this.props.totalLength) + this.props.currentBarX); } @action onScrubberUp = (e: PointerEvent) => { e.preventDefault(); e.stopPropagation(); document.removeEventListener("pointermove", this.onScrubberMove); document.removeEventListener("pointerup", this.onScrubberUp); } @action getTimes() { const vis = KeyframeFunc.convertPixelTime(this.props.visibleLength, "mili", "time", this.props.tickSpacing, this.props.tickIncrement); const x = KeyframeFunc.convertPixelTime(this.props.currentBarX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement); const start = KeyframeFunc.convertPixelTime(this.props.visibleStart, "mili", "time", this.props.tickSpacing, this.props.tickIncrement); this.visibleTime = vis; this.currentX = x; this.visibleStart = start; } render() { this.setOverviewWidth(); this.getTimes(); const percentVisible = this.visibleTime / this.props.time; const visibleBarWidth = percentVisible * this.activeOverviewWidth; const percentScrubberStart = this.currentX / this.props.time; let scrubberStart = this.props.currentBarX / this.props.totalLength * this.activeOverviewWidth; if (scrubberStart > this.activeOverviewWidth) scrubberStart = this.activeOverviewWidth; const percentBarStart = this.visibleStart / this.props.time; const barStart = percentBarStart * this.activeOverviewWidth; let playWidth = (this.props.currentBarX / this.props.totalLength) * this.activeOverviewWidth; if (playWidth > this.activeOverviewWidth) playWidth = this.activeOverviewWidth; const timeline = this.props.isAuthoring ? [
,
] : [
,
]; return (
{timeline}
); } }