diff options
5 files changed, 134 insertions, 31 deletions
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index dbc26e3d4..f6c04d43e 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -91,6 +91,8 @@ export namespace KeyframeFunc { regiondata.functions = new List<Doc>(); return regiondata; }; + + } export const RegionDataSchema = createSchema({ diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 97b9ad4db..a29758694 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import "./Timeline.scss"; -import { CollectionSubView } from "../collections/CollectionSubView"; +import { CollectionSubView, SubCollectionViewProps } from "../collections/CollectionSubView"; import { Document, listSpec } from "../../../new_fields/Schema"; import { observer } from "mobx-react"; import { Track } from "./Track"; @@ -35,8 +35,6 @@ export interface FlyoutProps { @observer export class Timeline extends CollectionSubView(Document) { - static Instance:Timeline; - private readonly DEFAULT_CONTAINER_HEIGHT: number = 300; private readonly DEFAULT_TICK_SPACING: number = 50; @@ -53,16 +51,16 @@ export class Timeline extends CollectionSubView(Document) { @observable private _trackbox = React.createRef<HTMLDivElement>(); @observable private _titleContainer = React.createRef<HTMLDivElement>(); @observable private _timelineContainer = React.createRef<HTMLDivElement>(); - @observable private _timelineWrapper = React.createRef<HTMLDivElement>(); @observable private _infoContainer = React.createRef<HTMLDivElement>(); - @observable private _currentBarX: number = 0; @observable private _windSpeed: number = 1; @observable private _isPlaying: boolean = false; //scrubber playing @observable private _isFrozen: boolean = false; //timeline freeze - @observable private _boxLength: number = 0; + @observable private _totalLength: number = 0; + @observable private _visibleLength: number = 0; + @observable private _visibleStart: number = 0; @observable private _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT; @observable private _time = 100000; //DEFAULT @observable private _ticks: number[] = []; @@ -83,8 +81,10 @@ export class Timeline extends CollectionSubView(Document) { return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)) as List<Doc>; } + componentWillMount() { this.props.Document.isAnimating ? this.props.Document.isAnimating = true : this.props.Document.isAnimating = false; + console.log(this._currentBarX); } componentDidMount() { @@ -99,11 +99,10 @@ export class Timeline extends CollectionSubView(Document) { this.changeCurrentBarX(curPage * this._tickIncrement / this._tickSpacing); }); } - } runInAction(() => { reaction(() => { - return this._time; + return this._time; }, () => { this._ticks = []; for (let i = 0; i < this._time;) { @@ -111,17 +110,22 @@ export class Timeline extends CollectionSubView(Document) { i += this._tickIncrement; } let trackbox = this._trackbox.current!; - this._boxLength = this._tickIncrement / 1000 * this._tickSpacing * this._ticks.length; - trackbox.style.width = `${this._boxLength}`; - this._scrubberbox.current!.style.width = `${this._boxLength}`; - }); + this._totalLength = this._tickSpacing * this._ticks.length; + trackbox.style.width = `${this._totalLength}`; + this._scrubberbox.current!.style.width = `${this._totalLength}`; + }, {fireImmediately:true}); + this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; + this._visibleStart = this._infoContainer.current!.scrollLeft; }); + } + + @action - changeCurrentBarX = (x: number) => { - this._currentBarX = x; + changeCurrentBarX = (pixel: number) => { + this._currentBarX = pixel; } //for playing @@ -139,10 +143,10 @@ export class Timeline extends CollectionSubView(Document) { @action changeCurrentX = () => { - if (this._currentBarX === this._boxLength && this._isPlaying) { + if (this._currentBarX === this._totalLength && this._isPlaying) { this._currentBarX = 0; } - if (this._currentBarX <= this._boxLength && this._isPlaying) { + if (this._currentBarX <= this._totalLength && this._isPlaying) { this._currentBarX = this._currentBarX + this._windSpeed; setTimeout(this.changeCurrentX, 15); } @@ -208,13 +212,18 @@ export class Timeline extends CollectionSubView(Document) { onPanMove = (e: PointerEvent) => { e.preventDefault(); e.stopPropagation(); - let infoContainer = this._infoContainer.current!; let trackbox = this._trackbox.current!; let titleContainer = this._titleContainer.current!; - infoContainer.scrollLeft = infoContainer.scrollLeft - e.movementX; + this.movePanX(this._visibleStart - e.movementX); trackbox.scrollTop = trackbox.scrollTop - e.movementY; titleContainer.scrollTop = titleContainer.scrollTop - e.movementY; } + @action + movePanX = (pixel:number) => { + let infoContainer = this._infoContainer.current!; + infoContainer.scrollLeft = pixel; + this._visibleStart = infoContainer.scrollLeft; + } @action @@ -276,7 +285,7 @@ export class Timeline extends CollectionSubView(Document) { } @action - toTime = (time: number): string => { + toReadTime = (time: number): string => { const inSeconds = time / 1000; let min: (string | number) = Math.floor(inSeconds / 60); let sec: (string | number) = inSeconds % 60; @@ -288,6 +297,23 @@ export class Timeline extends CollectionSubView(Document) { } + convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time") => { + let time = dir === "pixel" ? pos / this._tickSpacing * this._tickIncrement : pos * this._tickSpacing / this._tickIncrement; + switch (unit) { + case "mili": + return time; + case "sec": + return dir === "pixel" ? time / 1000 : time * 1000; + case "min": + return dir === "pixel" ? time / 60000 : time * 60000; + case "hr": + return dir === "pixel" ? time / 3600000 : time * 3600000; + default: + return time; + } + } + + private _freezeText = "Freeze Timeline"; timelineContextMenu = (e: React.MouseEvent): void => { @@ -337,22 +363,21 @@ export class Timeline extends CollectionSubView(Document) { } render() { - - return ( <div> <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}} ref={this._timelineWrapper}> <button key="timeline_minimize" className="minimize" onClick={this.minimize}>Minimize</button> <div key="timeline_container" className="timeline-container" style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }} ref={this._timelineContainer} onPointerDown={this.onTimelineDown} onContextMenu={this.timelineContextMenu}> <div key ="timeline_toolbox" className="timeline-toolbox"> - <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div> - <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div> - <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div> + <div key ="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div> + <div key ="timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="2x" /> </div> + <div key = "timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="2x" /> </div> + <TimelineOverview currentBarX = { this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> </div> <div key ="timeline_info"className="info-container" ref={this._infoContainer}> <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} onClick={this.onScrubberClick}> {this._ticks.map(element => { - return <div className="tick" style={{ transform: `translate(${element / 1000 * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toTime(element)}</p></div>; + return <div className="tick" style={{ transform: `translate(${element / 1000 * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>; })} </div> <div key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}> @@ -374,7 +399,7 @@ export class Timeline extends CollectionSubView(Document) { <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="4x" /> </div> <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} size="4x" /> </div> <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="4x" /> </div> - <TimelineOverview totalLength={this._time} visibleLength={20} visibleStart={0} changeCurrentBarX={this.changeCurrentBarX}/> + <TimelineOverview currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> </div> </div> ); diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss index a71abf348..21988927d 100644 --- a/src/client/views/animationtimeline/TimelineOverview.scss +++ b/src/client/views/animationtimeline/TimelineOverview.scss @@ -5,9 +5,33 @@ margin-left: 20px; background: white; border: 1px solid black; + padding: 0px; + display:inline-block; .timeline-overview-visible{ height: 100%; background: green; border: 1px solid black; + margin: 0px; + } + .timeline-overview-scrubber-container{ + height: 100%; + margin-top: -40px; + margin-left: 0px; + width: 2px; + z-index: 1001; + background-color:black; + display: inline-block; + .timeline-overview-scrubber-head{ + position:absolute; + height: 30px; + width: 30px; + background-color:transparent; + border-radius: 50%; + border: 5px solid black; + margin-left: -15px; + top: -15px; + + } + } }
\ No newline at end of file diff --git a/src/client/views/animationtimeline/TimelineOverview.tsx b/src/client/views/animationtimeline/TimelineOverview.tsx index 0e10e655d..1ad7d20e5 100644 --- a/src/client/views/animationtimeline/TimelineOverview.tsx +++ b/src/client/views/animationtimeline/TimelineOverview.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import {observable} from "mobx"; +import {observable, action} from "mobx"; import {observer} from "mobx-react"; import "./TimelineOverview.scss"; @@ -9,20 +9,71 @@ interface TimelineOverviewProps{ totalLength: number; visibleLength:number; visibleStart:number; - changeCurrentBarX: (x:number) => any; + currentBarX:number; + changeCurrentBarX: (pixel:number) => void; + movePanX: (pixel:number) => any; } +@observer export class TimelineOverview extends React.Component<TimelineOverviewProps>{ + @observable private _visibleRef = React.createRef<HTMLDivElement>(); + @observable private _scrubberRef = React.createRef<HTMLDivElement>(); + + @action + onPointerDown = (e:React.PointerEvent) => { + document.removeEventListener("pointermove", this.onPanX); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointermove", this.onPanX); + document.addEventListener("pointerup", this.onPointerUp); + } + + @action + onPanX = (e: PointerEvent) => { + let movX = (this.props.visibleStart / this.props.totalLength)* 300 + e.movementX; + this.props.movePanX((movX / 300) * this.props.totalLength); + } + + @action + onPointerUp = (e: PointerEvent) => { + 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(); + let scrubberRef = this._scrubberRef.current!; + let left = scrubberRef.getBoundingClientRect().left; + let offsetX = Math.round(e.clientX - left); + this.props.changeCurrentBarX(((offsetX / 300) * this.props.totalLength) + this.props.currentBarX); + } + + @action + onScrubberUp = (e:PointerEvent) => { + e.preventDefault(); + e.stopPropagation(); + document.removeEventListener("pointermove", this.onScrubberMove); + document.removeEventListener("pointerup", this.onScrubberUp); + } render(){ return( <div key="timeline-overview-container" className="timeline-overview-container"> - <div key="timeline-overview-visible" className="timeline-overview-visible" style={{left:`${this.props.visibleStart}px`, width:`${this.props.visibleLength}px`}}></div> - <div key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container"> + <div ref={this._visibleRef} key="timeline-overview-visible" className="timeline-overview-visible" style={{marginLeft:`${(this.props.visibleStart / this.props.totalLength)* 300}px`, width:`${(this.props.visibleLength / this.props.totalLength) * 300}px`}} onPointerDown={this.onPointerDown}></div> + <div ref={this._scrubberRef} key="timeline-overview-scrubber-container" className="timeline-overview-scrubber-container" style={{marginLeft:`${(this.props.currentBarX / this.props.totalLength) * 300}px`}} onPointerDown={this.onScrubberDown}> <div key="timeline-overview-scrubber-head" className="timeline-overview-scrubber-head"></div> - <div key="timeline-overview-scrubber-tail" className="tiemline-overview-scrubber-tail"></div> </div> </div> ); diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index 64e94f0f1..6bdabeb93 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -94,6 +94,7 @@ export class Track extends React.Component<IProps> { this.props.node.hidden = false; await this.timeChange(this.props.currentBarX); } else { + console.log("heuulloo"); this.props.node.hidden = true; } }, { fireImmediately: true }); |