aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/Keyframe.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/Keyframe.tsx')
-rw-r--r--src/client/views/nodes/Keyframe.tsx364
1 files changed, 198 insertions, 166 deletions
diff --git a/src/client/views/nodes/Keyframe.tsx b/src/client/views/nodes/Keyframe.tsx
index 76955da99..ed1f3b03a 100644
--- a/src/client/views/nodes/Keyframe.tsx
+++ b/src/client/views/nodes/Keyframe.tsx
@@ -1,87 +1,81 @@
import * as React from "react";
-import * as ReactDOM from "react-dom";
import "./Keyframe.scss";
-import "./../globalCssVariables.scss";
-import { observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS } from "mobx";
+import "./Timeline.scss";
+import "./../globalCssVariables.scss";
+import { observer, Observer } from "mobx-react";
+import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, isComputedProp } from "mobx";
import { Doc, DocListCast } from "../../../new_fields/Doc";
-import { auto } from "async";
import { Cast, FieldValue, StrCast, NumCast } from "../../../new_fields/Types";
-import { StandardLonghandProperties } from "csstype";
-import { runInThisContext } from "vm";
-import { DateField } from "../../../new_fields/DateField";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DocumentView } from "./DocumentView";
-import { anchorPoints, Flyout } from "../TemplateMenu";
-import { LinkMenu } from "./LinkMenu";
-import { faCircle } from "@fortawesome/free-solid-svg-icons";
-import { node, number } from "prop-types";
import { List } from "../../../new_fields/List";
import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../new_fields/Schema";
-import { CollectionBaseView } from "../collections/CollectionBaseView";
-import { notDeepEqual } from "assert";
-import { DocUtils, Docs } from "../../documents/Documents";
-import { DragLinksAsDocuments } from "../../util/DragManager";
-
-
-
+enum Direction {
+ left = "left",
+ right = "right"
+}
interface IProp {
node: Doc;
- keyframedata: Doc;
+ RegionData: Doc;
+ // routine: (innerFunc: () => void, args: any) => void;
}
-const KeyDataSchema = createSchema({});
-
-const TimeAndKeyDataSchema = createSchema({
+const KeyframeDataSchema = createSchema({
time: defaultSpec("number", 0),
key: Doc
});
-
-type KeyData = makeInterface<[typeof KeyDataSchema]>;
-type TimeAndKey = makeInterface<[typeof TimeAndKeyDataSchema]>;
-const KeyData = makeInterface(KeyDataSchema);
-const TimeAndKey = makeInterface(TimeAndKeyDataSchema);
+type KeyframeData = makeInterface<[typeof KeyframeDataSchema]>;
+const KeyframeData = makeInterface(KeyframeDataSchema);
-const KeyframeDataSchema = createSchema({
+const RegionDataSchema = createSchema({
position: defaultSpec("number", 0),
duration: defaultSpec("number", 0),
- kfs: listSpec(Doc)
-});
-
-type KeyframeData = makeInterface<[typeof KeyframeDataSchema]>;
-export const KeyframeData = makeInterface(KeyframeDataSchema);
-
+ keyframes: listSpec(Doc)
+});
+type RegionData = makeInterface<[typeof RegionDataSchema]>;
+export const RegionData = makeInterface(RegionDataSchema);
-@observer
-export class Keyframe extends React.Component<IProp> {
+interface FlyoutInfo {
+ position: number;
+ fadeIn: number;
+ fadeOut: number;
+}
- @observable private _display:string = "none";
- @observable private _duration:number = 200;
- @observable private _bar = React.createRef<HTMLDivElement>();
- @observable private _keyframes:number[] = [];
+const FlyoutObj = {
+ position: 0,
+ fadeIn: 0,
+ fadeOut: 1
+};
- private _reactionDisposers: IReactionDisposer[] = [];
- private _selectionManagerChanged?: IReactionDisposer;
+export var FlyoutInfoContext = React.createContext<FlyoutInfo>(FlyoutObj);
+@observer
+export class Keyframe extends React.Component<IProp> {
+ @observable private _display: string = "none";
+ @observable private _bar = React.createRef<HTMLDivElement>();
+ @observable private _keyframes: number[] = [];
+ @observable private position: number = 0;
+ @observable private fadein: number = 0;
+ @observable private fadeout: number = 0;
@action
componentDidMount() {
-
+
// need edge case here when keyframe data already exists when loading.....................;
- // let keyframes = Cast(this.props.node.keyframes, listSpec(Doc)) as List<Doc>;
- // if keyframes.indexOf()
+ this.fadein = 100;
+ FlyoutInfoContext = React.createContext<FlyoutInfo>({position: this.position,
+ fadeIn: this.fadein,
+ fadeOut: this.fadeout});
}
componentWillUnmount() {
-
+
}
-
+
// @action
// onPointerEnter = (e: React.PointerEvent) => {
// e.preventDefault();
@@ -96,138 +90,168 @@ export class Keyframe extends React.Component<IProp> {
// //this._display = "none";
// }
+
+ @computed
+ private get regiondata() {
+ let index = this.regions.indexOf(this.props.RegionData);
+ return RegionData(this.regions[index] as Doc);
+ }
+
@computed
- private get keyframes() {
- return Cast(this.props.node.keyframes, listSpec(Doc)) as List<Doc>;
+ private get regions() {
+ return Cast(this.props.node.regions, listSpec(Doc)) as List<Doc>;
}
- @action
+
+
+ @action
makeKeyData = (kfpos: number) => { //Kfpos is mouse offsetX, representing time
- let hasData = false;
- this.kfd.kfs!.forEach(TK => { //TK is TimeAndKey
- TK = TK as Doc;
- if (TK.time === kfpos){
- hasData = true;
+ let hasData = false;
+ this.regiondata.keyframes!.forEach(TK => { //TK is TimeAndKey
+ TK = TK as Doc;
+ if (TK.time === kfpos) {
+ hasData = true;
}
- });
- if (!hasData){
- let TK:Doc = new Doc();
- TK.time = kfpos;
- TK.key = Doc.MakeCopy(this.props.node);
- this.kfd.kfs!.push(TK);
- }
-
+ });
+ if (!hasData) {
+ let TK: Doc = new Doc();
+ TK.time = kfpos;
+ TK.key = Doc.MakeCopy(this.props.node);
+ this.regiondata.keyframes!.push(TK);
+ }
+
}
- @computed
- private get kfd(){
- let index = this.keyframes.indexOf(this.props.keyframedata);
- return KeyframeData(this.keyframes[index] as Doc);
- }
- @action
+ @action
onBarPointerDown = (e: React.PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- document.addEventListener("pointermove", this.onBarPointerMove);
- document.addEventListener("pointerup", (e:PointerEvent) => {
- document.removeEventListener("pointermove", this.onBarPointerMove);
- });
- }
-
- @action
- onBarPointerMove = (e:PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- if (this.kfd.position >= 0){
- let futureX = this.kfd.position + e.movementX;
- if (futureX <= 0){
- this.kfd.position = 0;
- } else{
- this.kfd.position += e.movementX;
+ e.preventDefault();
+ e.stopPropagation();
+ document.addEventListener("pointermove", this.onBarPointerMove);
+ document.addEventListener("pointerup", (e: PointerEvent) => {
+ document.removeEventListener("pointermove", this.onBarPointerMove);
+ });
+ }
+
+ @action
+ onBarPointerMove = (e: PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let left = this.findAdjacentRegion(Direction.left);
+ let right = this.findAdjacentRegion(Direction.right);
+ let futureX = this.regiondata.position + e.movementX;
+ 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 {
+ this.regiondata.position = futureX;
+ }
+
+ }
+
+ @action
+ findAdjacentRegion = (dir: Direction): (RegionData | undefined) => {
+ let leftMost: (RegionData | undefined) = undefined;
+ let rightMost: (RegionData | undefined) = undefined;
+ this.regions.forEach(region => {
+ let neighbor = RegionData(region as Doc);
+ if (this.regiondata.position > neighbor.position) {
+ if (!leftMost || neighbor.position > leftMost.position) {
+ leftMost = neighbor;
+ }
+ } else if (this.regiondata.position < neighbor.position) {
+ if (!rightMost || neighbor.position < rightMost.position) {
+ rightMost = neighbor;
+ }
}
+ });
+ if (dir === Direction.left) {
+ return leftMost;
+ } else if (dir === Direction.right) {
+ return rightMost;
}
}
- @action
- onResizeLeft = (e:React.PointerEvent)=>{
- e.preventDefault();
- e.stopPropagation();
- document.addEventListener("pointermove", this.onDragResizeLeft);
- document.addEventListener("pointerup", ()=>{
+ @action
+ onResizeLeft = (e: React.PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ document.addEventListener("pointermove", this.onDragResizeLeft);
+ document.addEventListener("pointerup", () => {
document.removeEventListener("pointermove", this.onDragResizeLeft);
- });
+ });
}
- @action
- onResizeRight = (e:React.PointerEvent)=> {
- e.preventDefault();
- e.stopPropagation();
- document.addEventListener("pointermove", this.onDragResizeRight);
- document.addEventListener("pointerup", ()=>{
+ @action
+ onResizeRight = (e: React.PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ document.addEventListener("pointermove", this.onDragResizeRight);
+ document.addEventListener("pointerup", () => {
document.removeEventListener("pointermove", this.onDragResizeRight);
- });
- }
-
- @action
- onDragResizeLeft = (e:PointerEvent)=>{
- e.preventDefault();
- e.stopPropagation();
- let bar = this._bar.current!;
- let barX = bar.getBoundingClientRect().left;
- let offset = e.clientX - barX;
- this._duration -= offset;
- this.kfd.position += offset;
- this.kfd.kfs!.forEach(kf => {
- kf = kf as Doc;
- kf.time = NumCast(kf.time) + offset;
- });
+ });
+ }
+
+ @action
+ onDragResizeLeft = (e: PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let bar = this._bar.current!;
+ let barX = bar.getBoundingClientRect().left;
+ let offset = e.clientX - barX;
+ this.regiondata.duration -= offset;
+ this.regiondata.position += offset;
+ this.regiondata.keyframes!.forEach(kf => {
+ kf = kf as Doc;
+ kf.time = NumCast(kf.time) + offset;
+ });
this._keyframes.forEach(num => {
- num += offset;
- });
- }
-
-
- @action
- onDragResizeRight = (e:PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let bar = this._bar.current!;
- let barX = bar.getBoundingClientRect().right;
- let offset = e.clientX - barX;
- console.log(offset);
- this._duration += offset;
- this.kfd.duration = this._duration;
- }
-
- createDivider = (type?: string):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>;
+ num -= offset;
+ });
+ }
+
+
+ @action
+ onDragResizeRight = (e: PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let bar = this._bar.current!;
+ let barX = bar.getBoundingClientRect().right;
+ let offset = e.clientX - barX;
+ console.log(offset);
+ this.regiondata.duration += offset;
+ }
+
+ createDivider = (type?: string): 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>;
+ return <div className="divider"></div>;
}
@action
createKeyframe = (e: React.MouseEvent) => {
- e.preventDefault();
- e.stopPropagation();
+ e.preventDefault();
+ e.stopPropagation();
let mouse = e.nativeEvent;
- let position = NumCast(this.props.keyframedata.position);
- this._keyframes.push(mouse.offsetX);
- this.makeKeyData(position + mouse.offsetX);
-
+ let position = NumCast(this.regiondata.position);
+ this._keyframes.push(mouse.offsetX);
+ this.makeKeyData(position + mouse.offsetX);
}
- @action
+ @action
onMenuHover = (e: React.PointerEvent) => {
- e.preventDefault();
- e.stopPropagation();
- if (this._display === "none"){
- this._display = "grid";
+ e.preventDefault();
+ e.stopPropagation();
+ if (this._display === "none") {
+ this._display = "grid";
} else {
- this._display = "none";
+ this._display = "none";
}
}
@@ -236,18 +260,26 @@ export class Keyframe extends React.Component<IProp> {
render() {
return (
<div>
- <div className="bar" ref={this._bar} style={{ transform: `translate(${this.props.keyframedata.position}px)`, width:`${this._duration}px`}} onPointerDown={this.onBarPointerDown} onDoubleClick={this.createKeyframe}>
- <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
- <div className="rightResize" onPointerDown={this.onResizeRight}></div>
- <div className="fadeLeft" style={{width:`${20}px`}}>{this.createDivider("left")}</div>
- <div className="fadeRight" style={{width:`${20}px`}}>{this.createDivider("right")}</div>
- {this._keyframes.map(kf => {return <div className="keyframe" style={{left: `${kf}px`}}>
- {this.createDivider()}
- <div className="keyframeCircle"></div>
- </div>;})}
- {this.createDivider("left")}
- {this.createDivider("right")}
- </div>
+ <FlyoutInfoContext.Provider value={{
+ position: this.position,
+ fadeOut: this.fadeout,
+ fadeIn: this.fadein
+ }}>
+ <div className="bar" ref={this._bar} style={{ transform: `translate(${this.regiondata.position}px)`, width: `${this.regiondata.duration}px` }} onPointerDown={this.onBarPointerDown} onDoubleClick={this.createKeyframe}>
+ <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
+ <div className="rightResize" onPointerDown={this.onResizeRight}></div>
+ <div className="fadeLeft" style={{ width: `${20}px` }}>{this.createDivider("left")}</div>
+ <div className="fadeRight" style={{ width: `${20}px` }}>{this.createDivider("right")}</div>
+ {this._keyframes.map(kf => {
+ return <div className="keyframe" style={{ left: `${kf}px` }}>
+ {this.createDivider()}
+ <div className="keyframeCircle"></div>
+ </div>;
+ })}
+ {this.createDivider("left")}
+ {this.createDivider("right")}
+ </div>
+ </FlyoutInfoContext.Provider>
</div>
);
}