diff options
| author | andrewdkim <adkim414@gmail.com> | 2019-10-02 15:59:56 -0400 |
|---|---|---|
| committer | andrewdkim <adkim414@gmail.com> | 2019-10-02 15:59:56 -0400 |
| commit | 00416cdb70aa8dd9698972ab0df8ca0a6c8575f9 (patch) | |
| tree | fb446dbdf8ff37d58aaa92019ae3edf72409900b /src/client/views/animationtimeline | |
| parent | 2f09822358dba784ec26d5707423b4025096ee45 (diff) | |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into animationtimeline_two
Diffstat (limited to 'src/client/views/animationtimeline')
| -rw-r--r-- | src/client/views/animationtimeline/Keyframe.tsx | 103 | ||||
| -rw-r--r-- | src/client/views/animationtimeline/Timeline.scss | 56 | ||||
| -rw-r--r-- | src/client/views/animationtimeline/Timeline.tsx | 152 | ||||
| -rw-r--r-- | src/client/views/animationtimeline/TimelineMenu.tsx | 11 | ||||
| -rw-r--r-- | src/client/views/animationtimeline/Track.tsx | 42 |
5 files changed, 156 insertions, 208 deletions
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index 7197f4b49..66ad6a76d 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -8,7 +8,6 @@ import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { Cast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema"; -import { FlyoutProps } from "./Timeline"; import { Transform } from "../../util/Transform"; import { InkField, StrokeData } from "../../../new_fields/InkField"; import { TimelineMenu } from "./TimelineMenu"; @@ -138,48 +137,13 @@ export class Keyframe extends React.Component<IProps> { @observable private _mouseToggled = false; @observable private _doubleClickEnabled = false; - @computed - private get regiondata() { - let index = this.regions.indexOf(this.props.RegionData); - return RegionData(this.regions[index] as Doc); - } - - @computed - private get regions() { - return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; - } - - @computed - private get firstKeyframe() { - let first: (Doc | undefined) = undefined; - DocListCast(this.regiondata.keyframes!).forEach(kf => { - if (kf.type !== KeyframeFunc.KeyframeType.fade) { - if (!first || first && NumCast(kf.time) < NumCast(first.time)) { - first = kf; - } - } - }); - return first; - } - - @computed - private get lastKeyframe() { - let last: (Doc | undefined) = undefined; - DocListCast(this.regiondata.keyframes!).forEach(kf => { - if (kf.type !== KeyframeFunc.KeyframeType.fade) { - if (!last || last && NumCast(kf.time) > NumCast(last.time)) { - last = kf; - } - } - }); - return last; - } - - @computed - private get keyframes(){ - return DocListCast(this.regiondata.keyframes); - } - + @computed private get regiondata() { return RegionData(this.regions[this.regions.indexOf(this.props.RegionData)] as Doc);} + @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;} + @computed private get keyframes(){ return DocListCast(this.regiondata.keyframes); } + @computed private get pixelPosition(){ return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement);} + @computed private get pixelDuration(){ return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } + @computed private get pixelFadeIn() { return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } + @computed private get pixelFadeOut(){ return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); } @computed private get inks() { if (this.props.collection.data_ext) { @@ -191,38 +155,18 @@ export class Keyframe extends React.Component<IProps> { } } - @computed - private get pixelPosition(){ - return KeyframeFunc.convertPixelTime(this.regiondata.position, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); - } - - @computed - private get pixelDuration(){ - return KeyframeFunc.convertPixelTime(this.regiondata.duration, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); - } - - @computed - private get pixelFadeIn() { - return KeyframeFunc.convertPixelTime(this.regiondata.fadeIn, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); - } - - @computed - private get pixelFadeOut(){ - return KeyframeFunc.convertPixelTime(this.regiondata.fadeOut, "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); - } - - async componentWillMount() { - if (!this.regiondata.keyframes) { - this.regiondata.keyframes = new List<Doc>(); - } - let fadeIn = await this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade)!; - let fadeOut = await this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade)!; - let start = await this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.fade)!; - let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!; - (fadeIn.key! as Doc).opacity = 1; - (fadeOut.key! as Doc).opacity = 1; - (start.key! as Doc).opacity = 0.1; - (finish.key! as Doc).opacity = 0.1; + componentWillMount() { + runInAction(async () => { + if (!this.regiondata.keyframes) this.regiondata.keyframes = new List<Doc>(); + let fadeIn = await this.makeKeyData(this.regiondata.position + this.regiondata.fadeIn, KeyframeFunc.KeyframeType.fade)!; + let fadeOut = await this.makeKeyData(this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut, KeyframeFunc.KeyframeType.fade)!; + let start = await this.makeKeyData(this.regiondata.position, KeyframeFunc.KeyframeType.fade)!; + let finish = await this.makeKeyData(this.regiondata.position + this.regiondata.duration, KeyframeFunc.KeyframeType.fade)!; + (fadeIn.key! as Doc).opacity = 1; + (fadeOut.key! as Doc).opacity = 1; + (start.key! as Doc).opacity = 0.1; + (finish.key! as Doc).opacity = 0.1; + }); } @action @@ -336,7 +280,7 @@ export class Keyframe extends React.Component<IProps> { let bar = this._bar.current!; let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement); let leftRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions); - let firstkf: (Doc | undefined) = this.firstKeyframe; + let firstkf: (Doc | undefined) = this.keyframes[0]; if (firstkf && this.regiondata.position + this.regiondata.fadeIn + offset >= NumCast(firstkf!.time)) { let dif = NumCast(firstkf!.time) - (this.pixelPosition + this.pixelFadeIn); this.regiondata.position = NumCast(firstkf!.time) - this.regiondata.fadeIn; @@ -364,8 +308,8 @@ export class Keyframe extends React.Component<IProps> { let bar = this._bar.current!; let offset = KeyframeFunc.convertPixelTime(Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement); let rightRegion = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions); - if (this.lastKeyframe! && this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.lastKeyframe! as Doc).time)) { - let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.lastKeyframe! as Doc).time); + if (this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut + offset <= NumCast((this.keyframes[this.keyframes.length - 1]).time)) { + let dif = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut - NumCast((this.keyframes[this.keyframes.length - 1]).time); this.regiondata.duration -= dif; } else if (this.regiondata.duration + offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // nokeyframes, just fades this.regiondata.duration = this.regiondata.fadeIn + this.regiondata.fadeOut; @@ -532,6 +476,7 @@ export class Keyframe extends React.Component<IProps> { e.stopPropagation(); let div = ref.current!; div.style.opacity = "1"; + Doc.BrushDoc(this.props.node); } onContainerOut = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => { @@ -539,6 +484,7 @@ export class Keyframe extends React.Component<IProps> { e.stopPropagation(); let div = ref.current!; div.style.opacity = "0"; + Doc.UnBrushDoc(this.props.node); } @@ -623,7 +569,6 @@ export class Keyframe extends React.Component<IProps> { } } render() { - console.log("RERENDERING"); return ( <div> <div className="bar" ref={this._bar} style={{ transform: `translate(${this.pixelPosition}px)`, diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss index 1457d5a84..09fc593fc 100644 --- a/src/client/views/animationtimeline/Timeline.scss +++ b/src/client/views/animationtimeline/Timeline.scss @@ -1,11 +1,6 @@ @import "./../globalCssVariables.scss"; -.minimize{ - position:relative; - z-index: 1000; - height: 30px; - width: 100px; -} + .timeline-toolbox{ position:absolute; @@ -17,6 +12,8 @@ margin-left:10px; } } + + .timeline-container{ width:100%; height:300px; @@ -37,12 +34,10 @@ background-color: transparent; height: 30px; width:100%; - .tick{ height:100%; width: 1px; background-color:black; - } } .scrubber{ @@ -119,4 +114,49 @@ width: 100%; background-color: grey; } +} + +.round-toggle { + position: absolute; + height: 40px; + width: 80px; + background-color: white; + border: 2px solid purple; + border-radius: 20px; + animation-fill-mode: forwards; + animation-duration: 500ms; + input{ + position:absolute; + opacity: 0; + height: 0; + width: 0; + } + .round-toggle-slider{ + position:absolute; + height: 35px; + width: 35px; + top: 0.5px; + background-color: white; + border:1px solid grey; + border-radius: 20px; + transition: transform 500ms ease-in-out; + + } + +} +@keyframes turnon{ + from{ + background-color: white; + } + to{ + background-color: purple; + } +} +@keyframes turnoff{ + from{ + background-color: purple; + } + to{ + background-color: white; + } }
\ No newline at end of file diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index c50ffa51b..8127e4de2 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -15,17 +15,6 @@ import { TimelineOverview } from "./TimelineOverview"; import { FieldViewProps } from "../nodes/FieldView"; import { KeyframeFunc } from "./Keyframe"; - - -export interface FlyoutProps { - x?: number; - y?: number; - display?: string; - regiondata?: Doc; - regions?: List<Doc>; -} - - @observer export class Timeline extends React.Component<FieldViewProps> { @@ -35,26 +24,23 @@ export class Timeline extends React.Component<FieldViewProps> { private readonly MAX_CONTAINER_HEIGHT: number = 800; private readonly DEFAULT_TICK_INCREMENT: number = 1000; - @observable private _isMinimized = false; - @observable private _tickSpacing = this.DEFAULT_TICK_SPACING; - @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT; - @observable private _scrubberbox = React.createRef<HTMLDivElement>(); - @observable private _scrubber = React.createRef<HTMLDivElement>(); @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 _roundToggleRef = React.createRef<HTMLDivElement>(); + @observable private _roundToggleContainerRef = React.createRef<HTMLDivElement>(); @observable private _currentBarX: number = 0; @observable private _windSpeed: number = 1; @observable private _isPlaying: boolean = false; //scrubber playing - @observable private _isFrozen: boolean = true; //timeline freeze @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 _containerHeight: number = this.DEFAULT_CONTAINER_HEIGHT; + @observable private _tickSpacing = this.DEFAULT_TICK_SPACING; + @observable private _tickIncrement = this.DEFAULT_TICK_INCREMENT; @observable private _time = 100000; //DEFAULT @observable private _ticks: number[] = []; @observable private _playButton = faPlayCircle; @@ -273,39 +259,7 @@ export class Timeline extends React.Component<FieldViewProps> { } } - @action - onTimelineDown = (e: React.PointerEvent) => { - e.preventDefault(); - if (e.nativeEvent.which === 1 && !this._isFrozen) { - document.addEventListener("pointermove", this.onTimelineMove); - document.addEventListener("pointerup", () => { document.removeEventListener("pointermove", this.onTimelineMove); }); - } - } - @action - onTimelineMove = (e: PointerEvent) => { - e.preventDefault(); - e.stopPropagation(); - let timelineContainer = this._timelineWrapper.current!; - let left = parseFloat(timelineContainer.style.left!); - let top = parseFloat(timelineContainer.style.top!); - timelineContainer.style.left = `${left + e.movementX}px`; - timelineContainer.style.top = `${top + e.movementY}px`; - } - - @action - minimize = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - let timelineContainer = this._timelineContainer.current!; - if (this._isMinimized) { - this._isMinimized = false; - timelineContainer.style.visibility = "visible"; - } else { - this._isMinimized = true; - timelineContainer.style.visibility = "hidden"; - } - } @action toReadTime = (time: number): string => { @@ -321,21 +275,6 @@ export class Timeline extends React.Component<FieldViewProps> { timelineContextMenu = (e:MouseEvent): void => { let subitems: ContextMenuProps[] = []; - let timelineContainer = this._timelineWrapper.current!; - subitems.push({ - description: "Pin to Top", event: action(() => { - if (!this._isFrozen) { - timelineContainer.style.left = "0px"; - timelineContainer.style.top = "0px"; - timelineContainer.style.transition = "none"; - } - }), icon: faArrowUp - }); - subitems.push({ - description: this._isFrozen ? "Unfreeze Timeline" : "Freeze Timeline", event: action(() => { - this._isFrozen = !this._isFrozen; - }), icon: "thumbtack" - }); subitems.push({ description: this._timelineVisible ? "Hide Timeline" : "Show Timeline", event: action(() => { this._timelineVisible = !this._timelineVisible; @@ -358,7 +297,8 @@ export class Timeline extends React.Component<FieldViewProps> { let currPixel = KeyframeFunc.convertPixelTime(prevTime, "mili", "pixel", this._tickSpacing, this._tickIncrement); let currCurrent = KeyframeFunc.convertPixelTime(prevCurrent, "mili", "pixel", this._tickSpacing, this._tickIncrement); this._infoContainer.current!.scrollLeft = currPixel - offset; - this._visibleStart = currPixel - offset; + this._visibleStart = currPixel - offset > 0 ? currPixel - offset : 0; + this._visibleStart += this._visibleLength + this._visibleStart > this._totalLength ? this._totalLength - (this._visibleStart + this._visibleLength) :0; this.changeCurrentBarX(currCurrent); } @@ -393,44 +333,70 @@ export class Timeline extends React.Component<FieldViewProps> { private timelineToolBox = (scale:number) => { let size = 50 * scale; //50 is default - return ( + return ( + <div key="timeline_toolbox" className="timeline-toolbox" style={{height:`${size}px`}}> - <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{height:`${size}px`, width: `${size}px`}} /> </div> - <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{height:`${size}px`, width: `${size}px`}} /> </div> - <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{height:`${size}px`, width: `${size}px`}} /> </div> - <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> + <div key="timeline_windBack" onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} style={{height:`${size}px`, width: `${size}px`}} /> </div> + <div key =" timeline_play" onClick={this.onPlay}> <FontAwesomeIcon icon={this._playButton} style={{height:`${size}px`, width: `${size}px`}} /> </div> + <div key="timeline_windForward" onClick={this.windForward}> <FontAwesomeIcon icon={faForward} style={{height:`${size}px`, width: `${size}px`}} /> </div> + <TimelineOverview scale={scale} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} visibleStart={this._visibleStart} changeCurrentBarX={this.changeCurrentBarX} movePanX={this.movePanX}/> + <div ref={this._roundToggleContainerRef}key="round-toggle" className="round-toggle"> + <div ref={this._roundToggleRef} className="round-toggle-slider" onPointerDown = {this.toggleChecked}> </div> + </div> </div> ); } + + @action + private toggleChecked = (e:React.PointerEvent) => { + e.preventDefault(); + e.stopPropagation(); + let roundToggle = this._roundToggleRef.current!; + let roundToggleContainer = this._roundToggleContainerRef.current!; + if (BoolCast(this.props.Document.isAnimating)){ + roundToggle.style.transform = "translate(0px, 0px)"; + roundToggle.style.animationName = "turnoff"; + roundToggleContainer.style.animationName = "turnoff"; + + this.props.Document.isAnimating = false; + } else { + roundToggle.style.transform = "translate(45px, 0px)"; + roundToggle.style.animationName = "turnon"; + roundToggleContainer.style.animationName = "turnon"; + this.props.Document.isAnimating = true; + } + } render() { return ( - <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}> - <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "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}> - {this.timelineToolBox(0.5)} - <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}> - <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}> - {this._ticks.map(element => { - if(element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement)* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>; - })} + <div> + <div style={{visibility: this._timelineVisible ? "visible" : "hidden"}}> + <div key="timeline_wrapper" style={{visibility: BoolCast(this.props.Document.isAnimating && this._timelineVisible) ? "visible" :"hidden", left: "0px", top: "0px", position: "absolute", width: "100%", transform: "translate(0px, 0px)"}}> + <div key="timeline_container" className="timeline-container" ref={this._timelineContainer} style={{ height: `${this._containerHeight}px`, left: "0px", top: "30px" }}> + <div key ="timeline_info"className="info-container" ref={this._infoContainer} onWheel={this.onWheelZoom}> + <div key="timeline_scrubberbox" className="scrubberbox" ref={this._scrubberbox} style={{width: `${this._totalLength}px`}} onClick={this.onScrubberClick}> + {this._ticks.map(element => { + if(element % this._tickIncrement === 0) return <div className="tick" style={{ transform: `translate(${(element / this._tickIncrement)* this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toReadTime(element)}</p></div>; + })} + </div> + <div key="timeline_scrubber" className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}> + <div key="timeline_scrubberhead" className="scrubberhead"></div> + </div> + <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}> + {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document} timelineVisible = {this._timelineVisible}/>)} + </div> </div> - <div key="timeline_scrubber" className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}> - <div key="timeline_scrubberhead" className="scrubberhead"></div> + <div key="timeline_title"className="title-container" ref={this._titleContainer}> + {DocListCast(this.children).map(doc => <div className="datapane" onPointerOver={() => {Doc.BrushDoc(doc);}} onPointerOut={() => {Doc.UnBrushDoc(doc);}}><p>{doc.title}</p></div>)} </div> - <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown} style={{width: `${this._totalLength}px`}}> - {DocListCast(this.children).map(doc => <Track node={doc} currentBarX={this._currentBarX} changeCurrentBarX={this.changeCurrentBarX} transform={this.props.ScreenToLocalTransform()} time={this._time} tickSpacing = {this._tickSpacing} tickIncrement ={this._tickIncrement} collection = {this.props.Document} timelineVisible = {this._timelineVisible}/>)} + <div key="timeline_resize" onPointerDown={this.onResizeDown}> + <FontAwesomeIcon className="resize" icon={faGripLines}/> </div> </div> - <div key="timeline_title"className="title-container" ref={this._titleContainer}> - {DocListCast(this.children).map(doc => <div className="datapane"><p>{doc.title}</p></div>)} - </div> - <div key="timeline_resize" onPointerDown={this.onResizeDown}> - <FontAwesomeIcon className="resize" icon={faGripLines} /> - </div> </div> + { this.timelineToolBox(1) } </div> - {BoolCast(this.props.Document.isAnimating) ? <div></div>: this.timelineToolBox(1) } + + </div> ); } diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx index f3b985297..59c25596e 100644 --- a/src/client/views/animationtimeline/TimelineMenu.tsx +++ b/src/client/views/animationtimeline/TimelineMenu.tsx @@ -4,6 +4,7 @@ import {observer} from "mobx-react"; import "./TimelineMenu.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChartLine, faRoad, faClipboard, faPen, faTrash, faTable } from "@fortawesome/free-solid-svg-icons"; +import { Utils } from "../../../Utils"; @observer @@ -40,7 +41,7 @@ export class TimelineMenu extends React.Component { if (type === "input"){ let inputRef = React.createRef<HTMLInputElement>(); let text = ""; - this._currentMenu.push(<div className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {inputRef} placeholder={title} onChange={(e) => { + this._currentMenu.push(<div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faClipboard} size="lg"/><input className="timeline-menu-input" ref = {inputRef} placeholder={title} onChange={(e) => { e.stopPropagation(); text = e.target.value; }} onKeyDown={(e) => { @@ -52,23 +53,23 @@ export class TimelineMenu extends React.Component { }}/></div>); } else if (type === "button") { let buttonRef = React.createRef<HTMLDivElement>(); - this._currentMenu.push( <div className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={(e) => { + this._currentMenu.push( <div key={Utils.GenerateGuid()} className="timeline-menu-item"><FontAwesomeIcon icon={faChartLine}size="lg"/><p className="timeline-menu-desc" onClick={(e) => { e.preventDefault(); e.stopPropagation(); event(e); this.closeMenu(); }}>{title}</p></div>); - } + } } @action addMenu = (title:string) => { - this._currentMenu.unshift(<div className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>); + this._currentMenu.unshift(<div key={Utils.GenerateGuid()} className="timeline-menu-header"><p className="timeline-menu-header-desc">{title}</p></div>); } render() { return ( - <div className="timeline-menu-container" style={{opacity: this._opacity, left: this._x, top: this._y}} > + <div key={Utils.GenerateGuid()} className="timeline-menu-container" style={{opacity: this._opacity, left: this._x, top: this._y}} > {this._currentMenu} </div> ); diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index c68d9bb3a..3ec410216 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -32,18 +32,24 @@ export class Track extends React.Component<IProps> { @observable private _onKeyframe: (Doc | undefined) = undefined; @observable private _onRegionData: (Doc | undefined) = undefined; @observable private _storedState: (Doc | undefined) = undefined; - - @computed - private get regions() { - return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>; - } + @observable private filterList = [ + "regions", + "cursors", + "hidden", + "nativeHeight", + "nativeWidth", + "schemaColumns", + "baseLayout", + "backgroundLayout", + "layout", + ]; + + @computed private get regions() { return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;} componentWillMount() { - if (!this.props.node.regions) { - this.props.node.regions = new List<Doc>(); - } - - + runInAction(() => { + if (!this.props.node.regions) this.props.node.regions = new List<Doc>(); + }); } componentDidMount() { @@ -54,11 +60,11 @@ export class Track extends React.Component<IProps> { this.props.node.hidden = false; this.props.node.opacity = 1; }); - } componentWillUnmount() { runInAction(() => { + //disposing reactions if (this._currentBarXReaction) this._currentBarXReaction(); if (this._timelineVisibleReaction) this._timelineVisibleReaction(); }); @@ -166,17 +172,7 @@ export class Track extends React.Component<IProps> { }); } - private filterList = [ - "regions", - "cursors", - "hidden", - "nativeHeight", - "nativeWidth", - "schemaColumns", - "baseLayout", - "backgroundLayout", - "layout", - ]; + @action private filterKeys = (keys: string[]): string[] => { @@ -294,7 +290,7 @@ export class Track extends React.Component<IProps> { return ( <div className="track-container"> <div className="track"> - <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick}> + <div className="inner" ref={this._inner} onDoubleClick={this.onInnerDoubleClick} onPointerOver = {() => {Doc.BrushDoc(this.props.node);}}onPointerOut={() => {Doc.UnBrushDoc(this.props.node);}}> {DocListCast(this.regions).map((region) => { return <Keyframe {...this.props} RegionData={region} />; })} |
