diff options
author | bobzel <zzzman@gmail.com> | 2022-05-05 11:58:41 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2022-05-05 11:58:41 -0400 |
commit | fefed2faee7808f75808f769496564d61d292d07 (patch) | |
tree | 3d1dd49388ff2ebf8c7cf1110779d3050ab638ca | |
parent | 32d46a0b641022cf0dd1fe0cf15629cf75057b59 (diff) |
fixed videobox ui sizing. added rotation for imageBoxs
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 36 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.scss | 43 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 7 |
3 files changed, 56 insertions, 30 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index fb8cfbc15..eb2bcc18c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -19,6 +19,7 @@ import { SelectionManager } from "../util/SelectionManager"; import { SnappingManager } from '../util/SnappingManager'; import { undoBatch, UndoManager } from "../util/UndoManager"; import { CollectionDockingView } from './collections/CollectionDockingView'; +import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { DocumentButtonBar } from './DocumentButtonBar'; import './DocumentDecorations.scss'; import { KeyManager } from './GlobalKeyHandler'; @@ -27,8 +28,8 @@ import { InkStrokeProperties } from './InkStrokeProperties'; import { LightboxView } from './LightboxView'; import { DocumentView } from "./nodes/DocumentView"; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { ImageBox } from './nodes/ImageBox'; import React = require("react"); -import { CollectionFreeFormView } from './collections/collectionFreeForm'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number, PanelHeight: number, boundsLeft: number, boundsTop: number }, { value: string }> { @@ -224,14 +225,18 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P @action onRotateDown = (e: React.PointerEvent): void => { const rotateUndo = UndoManager.StartBatch("rotatedown"); - const centerPoint = { X: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, Y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 }; + const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke); + const centerPoint = !selectedInk.length ? { X: this.Bounds.x, Y: this.Bounds.y } : { X: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, Y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 }; setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => { const previousPoint = { X: e.clientX, Y: e.clientY }; const movedPoint = { X: e.clientX - delta[0], Y: e.clientY - delta[1] }; const angle = InkStrokeProperties.angleChange(previousPoint, movedPoint, centerPoint); - const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke); - angle && InkStrokeProperties.Instance.rotateInk(selectedInk, -angle, centerPoint); + if (selectedInk.length) { + angle && InkStrokeProperties.Instance.rotateInk(selectedInk, -angle, centerPoint); + } else { + SelectionManager.Views().forEach(dv => dv.rootDoc._jitterRotation = NumCast(dv.rootDoc._jitterRotation) - angle * 180 / Math.PI); + } return false; }, () => { @@ -283,7 +288,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P if (fixedAspect && (resizeHdl === "documentDecorations-bottomRightResizer" || resizeHdl === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles const project = (p: number[], a: number[], b: number[]) => { const atob = [b[0] - a[0], b[1] - a[1]]; - const atop = [p[0] - a[0], p[1] - a[1]]; + const atop = [p[0] - a[0], p[1] - a[1]]; first const len = atob[0] * atob[0] + atob[1] * atob[1]; let dot = atop[0] * atob[0] + atop[1] * atob[1]; const t = dot / len; @@ -513,11 +518,16 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth)); bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight)); - const useRotation = seldoc.ComponentView instanceof InkingStroke; + const useRotation = seldoc.ComponentView instanceof InkingStroke || seldoc.ComponentView instanceof ImageBox; const resizerScheme = colorScheme ? "documentDecorations-resizer" + colorScheme : ""; + const rotation = NumCast(seldoc.rootDoc._jitterRotation) + const rdeg = rotation / 180 * Math.PI; + return (<div className={`documentDecorations${colorScheme}`}> <div className="documentDecorations-background" style={{ + transform: `rotate(${rotation}deg)`, + transformOrigin: "top left", width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px", left: bounds.x - this._resizeBorderWidth / 2, @@ -527,10 +537,10 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P }} onPointerDown={this.onBackgroundDown} onContextMenu={e => { e.preventDefault(); e.stopPropagation(); }} /> {bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <> <div className="documentDecorations-container" key="container" style={{ + transform: ` translate(${bounds.x - this._resizeBorderWidth / 2}px, ${bounds.y - this._resizeBorderWidth / 2 - this._titleHeight}px) rotate(${rotation}deg)`, + transformOrigin: `8px 26px`, width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", height: (bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight) + "px", - left: bounds.x - this._resizeBorderWidth / 2, - top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, }}> {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, e => this.onCloseClick(this.hasIcons ? true : undefined), "Close")} {titleArea} @@ -554,10 +564,14 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P onContextMenu={e => e.preventDefault()}>{useRotation && "⟲"}</div> </> } + {seldoc?.Document.type === DocumentType.FONTICON ? (null) : + <div className="link-button-container" key="links" + style={{ + transform: ` translate(${- this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, + }}> + <DocumentButtonBar views={SelectionManager.Views} /> + </div>} </div > - {seldoc?.Document.type === DocumentType.FONTICON ? (null) : <div className="link-button-container" key="links" style={{ left: bounds.x - this._resizeBorderWidth / 2 + 10, top: bounds.b + this._resizeBorderWidth / 2 }}> - <DocumentButtonBar views={SelectionManager.Views} /> - </div>} </>} </div > ); diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index f47a71469..f267407eb 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -15,6 +15,7 @@ width: 100%; height: 100%; position: relative; + .videoBox-viewer { display: flex; flex-direction: column; @@ -23,6 +24,7 @@ opacity: 0.99; // hack! overcomes some kind of Chrome weirdness where buttons (e.g., snapshot) disappear at some point as the video is resized larger background: $dark-gray; } + .inkingCanvas-paths-markers { opacity: 0.4; // we shouldn't have to do this, but since chrome crawls to a halt with z-index unset in videoBox-content, this is a workaround } @@ -52,17 +54,20 @@ width: 100%; z-index: -1; // 0; // logically this should be 0 (or unset) which would give us transparent brush strokes over videos. However, this makes Chrome crawl to a halt position: absolute; + video { width: auto; - height: 100%; - display: flex; + height: 100%; + display: flex; margin: auto; } } -.videoBox-content, .videoBox-content-interactive, .videoBox-content-fullScreen { +.videoBox-content, +.videoBox-content-interactive, +.videoBox-content-fullScreen { width: 100%; - height: 100%; + height: 100%; left: 0px; } @@ -82,17 +87,18 @@ justify-content: center; display: flex; width: 100%; + height: 38px; visibility: none; opacity: 0; background-color: $dark-gray; color: white; border-radius: 100px; - top: calc(100% - 20px); - left: 50%; - transform: translate(-50%, -100%); - + transform-origin: bottom left; + left: 0; + bottom: 0; + transition: top 0.5s, width 0.5s, opacity 0.2s, visibility 0s; - height: 120px; + height: 38px; padding: 0 20px; .timecode-controls { @@ -102,27 +108,28 @@ justify-content: center; margin: 0 5px; flex-grow: 2; - font-size: 32px; + font-size: 14px; .timecode { margin: 0 5px; } .timeline-slider { - margin: 0 20px 0 20px; + margin: 0 10px 0 10px; flex-grow: 2; } } - .toolbar-slider.volume, .toolbar-slider.zoom { + .toolbar-slider.volume, + .toolbar-slider.zoom { width: 100px; } .videobox-button { margin: 5px; cursor: pointer; - width: 70px; - height: 70px; + width: 38px; + height: 38px; border-radius: 50%; background: $dark-gray; display: flex; @@ -134,8 +141,8 @@ } svg { - width: 40px; - height: 40px; + width: 25px; + height: 25px; } } } @@ -151,6 +158,7 @@ pointer-events: all; padding-right: 5px; cursor: pointer; + &:hover { background-color: $medium-gray; } @@ -164,7 +172,8 @@ } } -.videoBox-content-fullScreen, .videoBox-content-fullScreen-interactive { +.videoBox-content-fullScreen, +.videoBox-content-fullScreen-interactive { display: flex; justify-content: center; align-items: center; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index c8b72990f..3b4c94562 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -694,7 +694,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // renders video controls @computed get uIButtons() { const curTime = NumCast(this.layoutDoc._currentTimecode) - (this.timeline?.clipStart || 0); - return <div className="videoBox-ui" style={this._fullScreen || this.heightPercent === 100 ? { fontSize: "40px", minWidth: "80%" } : {}}> + const scaling = (this.props.scaling?.() || 1); + return <div className="videoBox-ui" style={{ + transform: `scale(${1 / scaling})`, width: `${100 * scaling}%`, bottom: 20 / scaling + }}> <div className="videobox-button" title={this._playing ? "play" : "pause"} onPointerDown={this.onPlayDown}> @@ -745,7 +748,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp onPointerDown={(e) => { e.stopPropagation(); this.toggleMute(); }}> <FontAwesomeIcon icon={this._muted ? "volume-mute" : "volume-up"} /> </div> - <input type="range" step="0.1" min="0" max="1" value={this._muted ? 0 : this._volume} + <input type="range" style={{ width: `min(25%, 50px)` }} step="0.1" min="0" max="1" value={this._muted ? 0 : this._volume} className="toolbar-slider volume" onPointerDown={(e: React.PointerEvent) => e.stopPropagation()} onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.setVolume(Number(e.target.value))} |