diff options
author | andrewdkim <adkim414@gmail.com> | 2019-06-21 17:32:45 -0400 |
---|---|---|
committer | andrewdkim <adkim414@gmail.com> | 2019-06-21 17:32:45 -0400 |
commit | df5c4abc3acbf67db44384ef000c893c61270fcc (patch) | |
tree | 514e2a0c539c5b49f819ed4d0858bbb32072fd82 /src | |
parent | 1fa8e6c102b41bf99b7af9d803b6060284afc8b7 (diff) |
tick marks
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/nodes/Keyframe.scss | 9 | ||||
-rw-r--r-- | src/client/views/nodes/Keyframe.tsx | 99 | ||||
-rw-r--r-- | src/client/views/nodes/Timeline.scss | 44 | ||||
-rw-r--r-- | src/client/views/nodes/Timeline.tsx | 74 | ||||
-rw-r--r-- | src/client/views/nodes/Track.tsx | 14 |
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() { |