aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/views/nodes/DocumentView.tsx6
-rw-r--r--src/client/views/nodes/Keyframe.scss9
-rw-r--r--src/client/views/nodes/Keyframe.tsx99
-rw-r--r--src/client/views/nodes/Timeline.scss44
-rw-r--r--src/client/views/nodes/Timeline.tsx74
-rw-r--r--src/client/views/nodes/Track.tsx14
6 files changed, 180 insertions, 66 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 280804630..247e3223b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -89,7 +89,8 @@ const schema = createSchema({
nativeWidth: "number",
nativeHeight: "number",
backgroundColor: "string",
- hidden: "boolean"
+ hidden: "boolean",
+ opacity: "number"
});
export const positionSchema = createSchema({
@@ -559,7 +560,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
background: this.Document.backgroundColor || "",
width: nativeWidth,
height: nativeHeight,
- transform: `scale(${scaling}, ${scaling})`
+ transform: `scale(${scaling}, ${scaling})`,
+ opacity: this.Document.opacity || 1
}}
onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
diff --git a/src/client/views/nodes/Keyframe.scss b/src/client/views/nodes/Keyframe.scss
index 930384c7f..afc16e3c0 100644
--- a/src/client/views/nodes/Keyframe.scss
+++ b/src/client/views/nodes/Keyframe.scss
@@ -4,14 +4,14 @@
height: 100%;
width: 5px;
background-color: green;
- position: absolute;
+ position: relative;
// pointer-events: none;
.menubox {
width: 200px;
height: 200px;
top: 50%;
- position: absolute;
+ position: relative;
background-color: $light-color;
.menutable{
tr:nth-child(odd){
@@ -24,7 +24,9 @@
left:-10px;
height:20px;
width:20px;
- background-color: black;
+ border-radius: 50%;
+ border: 1px black;
+ background-color: transparent;
top: calc(50% - 10px);
position:absolute;
}
@@ -32,6 +34,7 @@
right:-10px;
height:20px;
width:20px;
+ border-radius: 50%;
top:calc(50% - 10px);
background-color:black;
position:absolute;
diff --git a/src/client/views/nodes/Keyframe.tsx b/src/client/views/nodes/Keyframe.tsx
index 6f7a7ec0b..b3dd251f9 100644
--- a/src/client/views/nodes/Keyframe.tsx
+++ b/src/client/views/nodes/Keyframe.tsx
@@ -11,13 +11,16 @@ 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";
+
interface IProp {
- collection?: Doc;
- node?: Doc;
- position: number;
+ node: Doc;
}
@observer
@@ -26,14 +29,21 @@ export class Keyframe extends React.Component<IProp> {
@observable private _display:string = "none";
@observable private _duration:number = 200;
@observable private _bar = React.createRef<HTMLDivElement>();
+ @observable private _data:Doc = new Doc();
+ @observable private _position:number = 0;
+
+ @action
componentDidMount() {
- console.log("mounted");
- if (this.props.node){
-
-
- }
- }
+ let dv:DocumentView = DocumentManager.Instance.getDocumentView(this.props.node!)!;
+ this._data = new Doc();
+ this._position = this.props.node.currentBarX as number;
+ this._data.duration = 200;
+ this._data.start = this._position - (this._duration/2);
+ this._data.end = this._position + (this._duration/2);
+
+
+ }
componentWillUnmount() {
@@ -54,6 +64,12 @@ export class Keyframe extends React.Component<IProp> {
}
@action
+ onBarPointerDown = (e: React.PointerEvent) => {
+ console.log(e.clientX);
+ this._position = e.clientX;
+ }
+
+ @action
onKeyDown = (e: React.KeyboardEvent) => {
e.preventDefault();
e.stopPropagation();
@@ -71,26 +87,31 @@ export class Keyframe extends React.Component<IProp> {
@action
onResizeLeft = (e:React.PointerEvent)=>{
+ e.preventDefault();
let bar = this._bar.current!;
- bar.addEventListener("pointermove", this.onDragResizeLeft);
+ document.addEventListener("pointermove", this.onDragResizeLeft);
}
@action
onDragResizeLeft = (e:PointerEvent)=>{
e.preventDefault();
- e.stopPropagation();
- let bar = this._bar.current!;
+ e.stopPropagation();
+ console.log("Dragging");
+ let bar = this._bar.current!;
let barX = bar.getBoundingClientRect().left;
let offset = barX - e.clientX;
bar.style.width = `${bar.getBoundingClientRect().width + offset}px`;
+ bar.style.transform = `translate(${e.clientX})`;
+ document.addEventListener("pointerup", this.onResizeFinished);
}
@action
- onResizeFinished =(e:React.PointerEvent) => {
+ onResizeFinished =(e:PointerEvent) => {
e.preventDefault();
e.stopPropagation();
let bar = this._bar.current!;
- bar.removeEventListener("pointermove", this.onDragResizeLeft);
+ document.removeEventListener("pointermove", this.onDragResizeLeft);
+ document.removeEventListener("pointermove", this.onDragResizeRight);
}
@action
@@ -98,46 +119,44 @@ export class Keyframe extends React.Component<IProp> {
e.preventDefault();
e.stopPropagation();
let bar = this._bar.current!;
- bar.addEventListener("pointermove", this.onDragResizeRight);
+ document.addEventListener("pointermove", this.onDragResizeRight);
}
@action
onDragResizeRight = (e:PointerEvent) => {
- e.preventDefault();
+ e.preventDefault();
e.stopPropagation();
let bar = this._bar.current!;
let barX = bar.getBoundingClientRect().right;
let offset = e.clientX - barX;
bar.style.width = `${bar.getBoundingClientRect().width + offset}px`;
+ document.addEventListener("pointerup", this.onResizeFinished);
+ }
+
+ @action
+ onResizeOut = (e:React.PointerEvent)=>{
+ let bar = this._bar.current!;
+ document.addEventListener("pointerup", this.onDragResizeRight);
+ }
+
+
+ @action
+ changeFlyoutContent = () => {
+
+ }
+
+ @action
+ onHover = (e:React.PointerEvent) => {
+
}
render() {
return (
<div>
- <div className="bar" ref={this._bar} style={{ transform: `translate(${this.props.position - (this._duration/2)}px)`, width:`${this._duration}px`}} onPointerOver={this.onPointerEnter} onPointerLeave={this.onPointerOut}>
- <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
- <div className="rightResize" onPointerDown={this.onResizeRight}></div>
- <div className="menubox" style={{display: this._display}}>
- {/* <table className="menutable">
- <tr>
- <th>Time: </th>
- <input placeholder={this.props.position.toString()}></input>
- </tr>
- <tr>
- </tr>
- <tr>
- <th onPointerDown={this.onPointerDown}>Title</th>
- <th>{this.props.node!.title}</th>
- </tr>
- <tr>
- <th>X</th>
- <th>{this.props.node!.x}</th>
- </tr>
- <tr>
- <th>Y</th>
- <th>{this.props.node!.y}</th>
- </tr>
- </table> */}
+ <div className="bar" ref={this._bar} style={{ transform: `translate(${this._position - (this._duration/2)}px)`, width:`${this._duration}px`}} onPointerDown={this.onBarPointerDown}>
+ <div className="leftResize" onPointerDown={this.onResizeLeft} ></div>
+ <div className="rightResize" onPointerDown={this.onResizeRight} onPointerOut={this.onResizeOut}></div>
+ <div className="menubox" style={{display: this._display}}>
</div>
</div>
</div>
diff --git a/src/client/views/nodes/Timeline.scss b/src/client/views/nodes/Timeline.scss
index a7b0323ff..4b35dcbe9 100644
--- a/src/client/views/nodes/Timeline.scss
+++ b/src/client/views/nodes/Timeline.scss
@@ -6,19 +6,45 @@
position:absolute;
background-color:$intermediate-color;
.toolbox{
- padding-top:10px;
+ width: 200px;
+ div{
+ position:relative;
+ display:inline-block;
+ }
}
.scrubberbox{
- z-index:10;
- background-color: black;
- height: 20px;
+ position:relative;
+ background-color: transparent;
+ height: 30px;
margin-left:calc(10% + 100px);
width: calc(80% - 100px);
- .scrubber{
- z-index:10;
- height:300px;
- width: 5px;
- background-color:green;
+ overflow-x: scroll;
+ overflow-y: visible;
+ .tick{
+ height:100%;
+ width: 1px;
+ background-color:black;
+
+ }
+
+ }
+ .scrubberbox::-webkit-scrollbar{
+ display:none;
+ }
+ .scrubber{
+ margin-left:calc(10% + 100px);
+ height: 100px;
+ width: 2px;
+ position:absolute;
+ z-index: 1001;
+
+ background-color:black ;
+ .scrubberhead{
+ height: 30px;
+ width: 30px;
+ left: -15px;
+ top: -30px;
+ position:absolute;
}
}
.trackbox{
diff --git a/src/client/views/nodes/Timeline.tsx b/src/client/views/nodes/Timeline.tsx
index c6118da91..c0f34ace5 100644
--- a/src/client/views/nodes/Timeline.tsx
+++ b/src/client/views/nodes/Timeline.tsx
@@ -11,6 +11,10 @@ import { SelectionManager } from "../../util/SelectionManager";
import { List } from "../../../new_fields/List";
import { Self } from "../../../new_fields/FieldSymbols";
import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faCircle, faPlayCircle, faBackward, faForward } from "@fortawesome/free-solid-svg-icons";
+
+
@observer
export class Timeline extends CollectionSubView(Document){
@@ -21,8 +25,9 @@ export class Timeline extends CollectionSubView(Document){
@observable private _isPlaying:boolean = false;
@observable private _boxLength:number = 0;
@observable private _nodes:List<Doc> = new List<Doc>();
-
+ @observable private _time = 100000; //DEFAULT
+ @observable private _ticks: number[] = [];
private _reactionDisposers: IReactionDisposer[] = [];
@@ -36,12 +41,26 @@ export class Timeline extends CollectionSubView(Document){
}
let childrenList = ((children[Self] as any).__fields) as List<Doc>;
this._nodes = (childrenList) as List<Doc>;
+
+
+ //check if this is a video frame
+
+ let boxWidth = scrubber.getBoundingClientRect().width;
+ for (let i = 0; i < this._time; ) {
+ this._ticks.push(i);
+ i += 1000;
+ }
+
}
componentWillUnmount(){
}
+
+
+
+ //for playing
@action
onPlay = async (e: React.MouseEvent) => {
if (this._isPlaying) {
@@ -77,28 +96,69 @@ export class Timeline extends CollectionSubView(Document){
}
}
+ //for scrubber action
@action
onScrubberDown = (e:React.PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let scrubberbox = this._scrubberbox.current!;
+ //let left = scrubberbox.getBoundingClientRect().left;
+
+ //let offsetX = Math.round(e.clientX - left);
+ let mouse = e.nativeEvent;
+ this._currentBarX = mouse.offsetX;
+ document.addEventListener("pointermove", this.onScrubberMove);
+ document.addEventListener("pointerup", this.onScrubberFinished);
+ }
+
+ @action
+ onScrubberMove = (e: PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
let scrubberbox = this._scrubberbox.current!;
let left = scrubberbox.getBoundingClientRect().left;
let offsetX = Math.round(e.clientX - left);
this._currentBarX = offsetX;
}
+ onScrubberFinished = (e: PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let scrubberbox = this._scrubberbox.current!;
+ document.removeEventListener("pointermove", this.onScrubberMove);
+ }
+
+ toTime = (time:number):string => {
+ const inSeconds = time / 1000;
+ let min:(string|number) = Math.floor(inSeconds / 60);
+ let sec:(string|number) = inSeconds % 60;
+
+ if (Math.floor(sec/10) === 0){
+ sec = "0" + sec;
+ }
+ return `${min}:${sec}`;
+
+ }
+
render(){
return (
<div className="timeline-container">
<div className="toolbox">
- <button onClick={this.windBackward}> {"<"} </button>
- <button onClick={this.onPlay}> Play </button>
- <button onClick={this.windForward}> {">"} </button>
+ <div onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="lg"/> </div>
+ <div onClick={this.onPlay}> <FontAwesomeIcon icon={faPlayCircle} size="lg"/> </div>
+ <div onClick={this.windForward}> <FontAwesomeIcon icon={faForward} size="lg"/> </div>
</div>
- <div className="scrubberbox" onPointerDown={this.onScrubberDown} ref ={this._scrubberbox}>
- <div className="scrubber" style={{transform:`translate(${this._currentBarX}px)`}}></div>
+ <div></div>
+ <div className="scrubberbox" ref ={this._scrubberbox}>
+ {this._ticks.map(element => {return <div className="tick" style={{transform:`translate(${element / 20}px)`, position:"absolute"}}> <p>{this.toTime(element)}</p></div>})}
+
+ </div>
+ <div className="scrubber" onPointerDown = {this.onScrubberDown} style={{transform:`translate(${this._currentBarX}px)`}}>
+ <FontAwesomeIcon className="scrubberhead" icon={faCircle}/>;
</div>
<div className="trackbox">
- {this._nodes.map(doc => {return <Track node={(doc as any).value() as Doc}/>})}
+ {this._nodes.map(doc => {return <Track node={(doc as any).value() as Doc}/>;})}
</div>
</div>
);
diff --git a/src/client/views/nodes/Track.tsx b/src/client/views/nodes/Track.tsx
index dab73ce06..d7ef68f70 100644
--- a/src/client/views/nodes/Track.tsx
+++ b/src/client/views/nodes/Track.tsx
@@ -303,11 +303,12 @@ export class Track extends React.Component<props> {
// this.props.Document.keyframes = new List<List<Doc>>();
// }
- let keys = Doc.allKeys(this.props.node);
+ // let keys = Doc.allKeys(this.props.node);
+ // return reaction(() => keys.map(key => FieldValue(this.props.node[key])), data => {
+ // console.log(data);
+ // });
- return reaction(() => keys.map(key => FieldValue(this.props.node[key])), data => {
- console.log(data);
- });
+ this.props.node.currentBarX = this._currentBarX;
}
/**
@@ -401,7 +402,10 @@ export class Track extends React.Component<props> {
let inner = this._inner.current!;
let left = inner.getBoundingClientRect().left;
let offsetX = Math.round(e.clientX - left);
- this._keyframes.push(<Keyframe position={offsetX} />);
+ this.props.node.currentBarX = offsetX;
+ this._keyframes.push(<Keyframe node={this.props.node}/>);
+
+
}
render() {