diff options
| author | andrewdkim <adkim414@gmail.com> | 2019-08-16 17:26:43 -0400 |
|---|---|---|
| committer | andrewdkim <adkim414@gmail.com> | 2019-08-16 17:26:43 -0400 |
| commit | 8ab017ac1928db4a9a9f8eb6b579245814cde725 (patch) | |
| tree | 6356f38e92e097e0217225d01d1a2f55608be905 /src/client/views/animationtimeline/Keyframe.tsx | |
| parent | 078abf5548a18945527f12dde1a79095bd30e50e (diff) | |
zooming fixes
Diffstat (limited to 'src/client/views/animationtimeline/Keyframe.tsx')
| -rw-r--r-- | src/client/views/animationtimeline/Keyframe.tsx | 169 |
1 files changed, 93 insertions, 76 deletions
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index 4e58b07d8..b02d89bf0 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -82,16 +82,30 @@ export namespace KeyframeFunc { }; export const defaultKeyframe = () => { - let regiondata = new Doc(); //creating regiondata - regiondata.duration = 200; + let regiondata = new Doc(); //creating regiondata in MILI + regiondata.duration = 4000; regiondata.position = 0; - regiondata.fadeIn = 20; - regiondata.fadeOut = 20; + regiondata.fadeIn = 1000; + regiondata.fadeOut = 1000; regiondata.functions = new List<Doc>(); return regiondata; }; - + export const convertPixelTime = (pos: number, unit: "mili" | "sec" | "min" | "hr", dir: "pixel" | "time", tickSpacing:number, tickIncrement:number) => { + let time = dir === "pixel" ? (pos * tickSpacing) / tickIncrement : (pos / tickSpacing) * 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; + } + }; } export const RegionDataSchema = createSchema({ @@ -109,6 +123,9 @@ interface IProps { node: Doc; RegionData: Doc; collection: Doc; + tickSpacing: number; + tickIncrement: number; + time: number; changeCurrentBarX: (x: number) => void; transform: Transform; } @@ -118,6 +135,8 @@ export class Keyframe extends React.Component<IProps> { @observable private _bar = React.createRef<HTMLDivElement>(); @observable private _gain = 20; //default + @observable private _mouseToggled = false; + @observable private _doubleClickEnabled = false; @computed private get regiondata() { @@ -155,6 +174,7 @@ export class Keyframe extends React.Component<IProps> { }); return last; } + @computed private get keyframes(){ return DocListCast(this.regiondata.keyframes); @@ -171,6 +191,26 @@ 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>(); @@ -183,20 +223,6 @@ export class Keyframe extends React.Component<IProps> { (fadeOut.key! as Doc).opacity = 1; (start.key! as Doc).opacity = 0.1; (finish.key! as Doc).opacity = 0.1; - - observe(this.regiondata, change => { - if (change.type === "update") { - fadeIn.time = this.regiondata.position + this.regiondata.fadeIn; - fadeOut.time = this.regiondata.position + this.regiondata.duration - this.regiondata.fadeOut; - start.time = this.regiondata.position; - finish.time = this.regiondata.position + this.regiondata.duration; - this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(fadeIn)] = fadeIn; - this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(fadeOut)] = fadeOut; - this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(start)] = start; - this.regiondata.keyframes![this.regiondata.keyframes!.indexOf(finish)] = finish; - this.forceUpdate(); - } - }); } @action @@ -236,8 +262,7 @@ export class Keyframe extends React.Component<IProps> { return TK; } - @observable private _mouseToggled = false; - @observable private _doubleClickEnabled = false; + @action onBarPointerDown = (e: React.PointerEvent) => { e.preventDefault(); @@ -247,14 +272,14 @@ export class Keyframe extends React.Component<IProps> { this.createKeyframe(clientX); this._doubleClickEnabled = false; } else { - setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.regiondata.position + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale); + setTimeout(() => {if(!this._mouseToggled && this._doubleClickEnabled)this.props.changeCurrentBarX(this.pixelPosition + (clientX - this._bar.current!.getBoundingClientRect().left) * this.props.transform.Scale); this._mouseToggled = false; this._doubleClickEnabled = false; }, 200); this._doubleClickEnabled = true; document.addEventListener("pointermove", this.onBarPointerMove); document.addEventListener("pointerup", (e: PointerEvent) => { document.removeEventListener("pointermove", this.onBarPointerMove); - }); + }); } } @@ -269,23 +294,20 @@ export class Keyframe extends React.Component<IProps> { let left = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.left, this.regiondata, this.regions)!; let right = KeyframeFunc.findAdjacentRegion(KeyframeFunc.Direction.right, this.regiondata, this.regions!); let prevX = this.regiondata.position; - let futureX = this.regiondata.position + e.movementX; + let futureX = this.regiondata.position + KeyframeFunc.convertPixelTime(e.movementX, "mili", "time", this.props.tickSpacing, this.props.tickIncrement); if (futureX <= 0) { this.regiondata.position = 0; } else if ((left && left.position + left.duration >= futureX)) { this.regiondata.position = left.position + left.duration; - } else if ((right && right.position <= futureX + this.regiondata.duration)) { - this.regiondata.position = right.position - this.regiondata.duration; + } else if ((right && right.position <= futureX + this.pixelDuration)) { + this.regiondata.position = right.position - this.pixelDuration; } else { this.regiondata.position = futureX; - } - for (let i = 0; i < this.regiondata.keyframes!.length; i++) { - if ((this.regiondata.keyframes![i] as Doc).type !== KeyframeFunc.KeyframeType.fade) { - let movement = this.regiondata.position - prevX; - (this.regiondata.keyframes![i] as Doc).time = NumCast((this.regiondata.keyframes![i] as Doc).time) + movement; - } - } - this.forceUpdate(); + } + let movement = this.regiondata.position - prevX; + this.keyframes.forEach(kf => { + kf.time = NumCast(kf.time) + movement; + }); } @action @@ -313,11 +335,11 @@ export class Keyframe extends React.Component<IProps> { e.preventDefault(); e.stopPropagation(); let bar = this._bar.current!; - let offset = Math.round((e.clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale); + 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; if (firstkf && this.regiondata.position + this.regiondata.fadeIn + offset >= NumCast(firstkf!.time)) { - let dif = NumCast(firstkf!.time) - (this.regiondata.position + this.regiondata.fadeIn); + let dif = NumCast(firstkf!.time) - (this.pixelPosition + this.pixelFadeIn); this.regiondata.position = NumCast(firstkf!.time) - this.regiondata.fadeIn; this.regiondata.duration -= dif; } else if (this.regiondata.duration - offset < this.regiondata.fadeIn + this.regiondata.fadeOut) { // no keyframes, just fades @@ -331,6 +353,7 @@ export class Keyframe extends React.Component<IProps> { this.regiondata.duration -= offset; this.regiondata.position += offset; } + } @@ -339,7 +362,7 @@ export class Keyframe extends React.Component<IProps> { e.preventDefault(); e.stopPropagation(); let bar = this._bar.current!; - let offset = Math.round((e.clientX - bar.getBoundingClientRect().right) * this.props.transform.Scale); + 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); @@ -352,27 +375,18 @@ export class Keyframe extends React.Component<IProps> { } else { this.regiondata.duration += offset; } - } - - createDivider = (type?: KeyframeFunc.Direction): JSX.Element => { - if (type === "left") { - return <div className="divider" style={{ right: "0px" }}></div>; - } else if (type === "right") { - return <div className="divider" style={{ left: "0px" }}> </div>; - } - return <div className="divider"></div>; + } @action createKeyframe = async (clientX:number) => { this._mouseToggled = true; let bar = this._bar.current!; - let offset = Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale); + let offset = KeyframeFunc.convertPixelTime(Math.round((clientX - bar.getBoundingClientRect().left) * this.props.transform.Scale), "mili", "time", this.props.tickSpacing, this.props.tickIncrement); if (offset > this.regiondata.fadeIn && offset < this.regiondata.duration - this.regiondata.fadeOut) { //make sure keyframe is not created inbetween fades and ends - let position = NumCast(this.regiondata.position); + let position = this.regiondata.position; await this.makeKeyData(Math.round(position + offset)); - console.log(this.regiondata.keyframes!.length); - this.props.changeCurrentBarX(NumCast(Math.round(position + offset))); //first move the keyframe to the correct location and make a copy so the correct file gets coppied + this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(Math.round(position + offset), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); //first move the keyframe to the correct location and make a copy so the correct file gets coppied } } @@ -381,7 +395,7 @@ export class Keyframe extends React.Component<IProps> { moveKeyframe = async (e: React.MouseEvent, kf: Doc) => { e.preventDefault(); e.stopPropagation(); - this.props.changeCurrentBarX(NumCast(kf.time!)); + this.props.changeCurrentBarX(KeyframeFunc.convertPixelTime(NumCast(kf.time!), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement)); } @@ -390,33 +404,38 @@ export class Keyframe extends React.Component<IProps> { e.preventDefault(); e.stopPropagation(); this.props.node.backgroundColor = "#000000"; - } + + @action + makeKeyframeMenu = (kf :Doc, e:MouseEvent) => { + let items = [ + TimelineMenu.Instance.addItem("button", "Show Data", () => { + runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); + CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); }); + }), + TimelineMenu.Instance.addItem("button", "Delete", () => {}), + TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);}) + ]; + TimelineMenu.Instance.addMenu("Keyframe", items); + TimelineMenu.Instance.openMenu(e.clientX, e.clientY); +} @action private createKeyframeJSX = (kf: Doc, type = KeyframeFunc.KeyframeType.default) => { if (type === KeyframeFunc.KeyframeType.default) { return ( - <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}> - {this.createDivider()} + <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}> + <div className="divider"></div> <div className="keyframeCircle" onPointerDown={(e) => { this.moveKeyframe(e, kf as Doc); }} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); - let items = [ - TimelineMenu.Instance.addItem("button", "Show Data", () => { - runInAction(() => {let kvp = Docs.Create.KVPDocument(Cast(kf.key, Doc) as Doc, { width: 300, height: 300 }); - CollectionDockingView.Instance.AddRightSplit(kvp, (kf.key as Doc).data as Doc); }); - }), - TimelineMenu.Instance.addItem("button", "Delete", () => {}), - TimelineMenu.Instance.addItem("input", "Move", (val) => {kf.time = parseInt(val, 10);}) - ]; - TimelineMenu.Instance.addMenu("Keyframe", items); - TimelineMenu.Instance.openMenu(e.clientX, e.clientY); + this.makeKeyframeMenu(kf, e.nativeEvent); }}></div> - </div>); + </div> + ); } return ( - <div className="keyframe" style={{ left: `${NumCast(kf.time) - this.regiondata.position}px` }}> - {this.createDivider()} + <div className="keyframe" style={{ left: `${KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement) - this.pixelPosition}px` }}> + <div className="divider"></div> </div> ); } @@ -460,9 +479,6 @@ export class Keyframe extends React.Component<IProps> { } - - - @action onReactionListen = (e: PointerEvent) => { e.preventDefault(); @@ -514,7 +530,6 @@ export class Keyframe extends React.Component<IProps> { (Cast(this.regiondata.functions![index], Doc) as Doc).pathX = xPlots; (Cast(this.regiondata.functions![index], Doc) as Doc).pathY = yPlots; } - this._reac = undefined; this._interpolationKeyframe = undefined; this._plotList = undefined; @@ -525,19 +540,21 @@ export class Keyframe extends React.Component<IProps> { render() { return ( <div> - <div className="bar" ref={this._bar} style={{ transform: `translate(${this.regiondata.position}px)`, width: `${this.regiondata.duration}px`, background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.regiondata.fadeIn / this.regiondata.duration * 100}%, rgba(77, 153, 0, 1) ${(this.regiondata.duration - this.regiondata.fadeOut) / this.regiondata.duration * 100}%, rgba(77, 153, 0, 0) 100% )` }} + <div className="bar" ref={this._bar} style={{ transform: `translate(${this.pixelPosition}px)`, + width: `${this.pixelDuration}px`, + background: `linear-gradient(90deg, rgba(77, 153, 0, 0) 0%, rgba(77, 153, 0, 1) ${this.pixelFadeIn / this.pixelDuration}%, rgba(77, 153, 0, 1) ${(this.pixelDuration - this.pixelFadeOut) / this.pixelDuration * 100}%, rgba(77, 153, 0, 0) 100% )` }} onPointerDown={this.onBarPointerDown}> <div className="leftResize" onPointerDown={this.onResizeLeft} ></div> <div className="rightResize" onPointerDown={this.onResizeRight}></div> - {this.regiondata.keyframes!.map(kf => { - return this.createKeyframeJSX(kf as Doc, (kf! as Doc).type as KeyframeFunc.KeyframeType); - })} + {this.keyframes.map(kf => { this.createKeyframeJSX(kf, kf.type as KeyframeFunc.KeyframeType); })} {this.keyframes.map( kf => { if(this.keyframes.indexOf(kf ) !== this.keyframes.length - 1) { let left = this.keyframes[this.keyframes.indexOf(kf) + 1]; let bodyRef = React.createRef<HTMLDivElement>(); + let kfPos = KeyframeFunc.convertPixelTime(NumCast(kf.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); + let leftPos = KeyframeFunc.convertPixelTime(NumCast(left!.time), "mili", "pixel", this.props.tickSpacing, this.props.tickIncrement); return ( - <div ref={bodyRef}className="body-container" style={{left: `${NumCast(kf.time) - this.regiondata.position}px`, width:`${NumCast(left!.time) - NumCast(kf.time)}px`}} + <div ref={bodyRef}className="body-container" style={{left: `${kfPos - this.pixelPosition}px`, width:`${leftPos - kfPos}px`}} onPointerOver={(e) => { this.onContainerOver(e, bodyRef); }} onPointerOut={(e) => { this.onContainerOut(e, bodyRef); }} onContextMenu={(e) => { |
