diff options
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 0a4168698..5982d4d66 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -14,6 +14,8 @@ import { TraceMobx } from '../../../fields/util'; import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../Utils'; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices'; +import { Docs, DocUtils } from '../../documents/Documents'; +import { DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DragManager } from '../../util/DragManager'; @@ -45,7 +47,6 @@ const uploadIcons = { export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() { protected _multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined; public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ImageBox, fieldKey); } - private _imgRef: React.RefObject<HTMLImageElement> = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; @observable _curSuffix = ""; @@ -74,11 +75,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp scrSize: this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0], selected: this.props.isSelected() }), - ({ forceFull, scrSize, selected }) => this._curSuffix = forceFull ? "_o" : scrSize < 100 ? "_s" : scrSize < 400 ? "_m" : scrSize < 800 || !selected ? "_l" : "_o", + ({ forceFull, scrSize, selected }) => this._curSuffix = this.fieldKey === "icon" ? "_m" : forceFull ? "_o" : scrSize < 100 ? "_s" : scrSize < 400 ? "_m" : scrSize < 800 || !selected ? "_l" : "_o", { fireImmediately: true, delay: 1000 }); this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), ({ nativeSize, width }) => { - if (!this.layoutDoc._height) { + if (true || !this.layoutDoc._height) { this.layoutDoc._height = width * nativeSize.nativeHeight / nativeSize.nativeWidth; } }, @@ -128,6 +129,48 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.layoutDoc._height = w; }); + crop = (region: Doc | undefined, addCrop?: boolean) => { + if (!region) return; + const cropping = Doc.MakeCopy(region, true); + Doc.GetProto(region).lockedPosition = true; + Doc.GetProto(region).title = "region:" + this.rootDoc.title; + Doc.GetProto(region).isPushpin = true; + this.addDocument(region); + const anchx = NumCast(cropping.x); + const anchy = NumCast(cropping.y); + const anchw = NumCast(cropping._width); + const anchh = NumCast(cropping._height); + const viewScale = NumCast(this.rootDoc[this.fieldKey + "-nativeWidth"]) / anchw; + cropping.title = "crop: " + this.rootDoc.title; + cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width); + cropping.y = NumCast(this.rootDoc.y); + cropping._width = anchw * (this.props.scaling?.() || 1); + cropping._height = anchh * (this.props.scaling?.() || 1); + cropping.isLinkButton = undefined; + const croppingProto = Doc.GetProto(cropping); + croppingProto.annotationOn = undefined; + croppingProto.isPrototype = true; + croppingProto.proto = Cast(this.rootDoc.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO + croppingProto.type = DocumentType.IMG; + croppingProto.layout = ImageBox.LayoutString("data"); + croppingProto.data = ObjectField.MakeCopy(this.rootDoc[this.fieldKey] as ObjectField); + croppingProto["data-nativeWidth"] = anchw; + croppingProto["data-nativeHeight"] = anchh; + croppingProto.viewScale = viewScale; + croppingProto.viewScaleMin = viewScale; + croppingProto.panX = anchx / viewScale; + croppingProto.panY = anchy / viewScale; + croppingProto.panXMin = (anchx) / viewScale; + croppingProto.panXMax = (anchw) / viewScale; + croppingProto.panYMin = (anchy) / viewScale; + croppingProto.panYMax = (anchh) / viewScale; + if (addCrop) { + DocUtils.MakeLink({ doc: region }, { doc: cropping }, "cropped image", ""); + } + this.props.bringToFront(cropping); + return cropping; + } + specificContextMenu = (e: React.MouseEvent): void => { const field = Cast(this.dataDoc[this.fieldKey], ImageField); if (field) { @@ -246,8 +289,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @computed get nativeSize() { TraceMobx(); - const nativeWidth = NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"], 500); - const nativeHeight = NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"], 1); + const nativeWidth = NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"], NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"], 500)); + const nativeHeight = NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"], NumCast(this.layoutDoc[this.fieldKey + "-nativeHeight"], 1)); const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + "-nativeOrientation"], 1); return { nativeWidth, nativeHeight, nativeOrientation }; } @@ -282,17 +325,18 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return <div className="imageBox-cont" key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}> <div className="imageBox-fader" style={{ overflow: Array.from(this.props.docViewPath?.()).slice(-1)[0].fitWidth ? "auto" : undefined }} > - <img key="paths" ref={this._imgRef} + <img key="paths" src={srcpath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} /> - {fadepath === srcpath ? (null) : <div className="imageBox-fadeBlocker"> - <img className="imageBox-fadeaway" key={"fadeaway"} ref={this._imgRef} - src={fadepath} - style={{ transform, transformOrigin }} draggable={false} - width={nativeWidth} /> - </div>} + {fadepath === srcpath ? (null) : + <div className={`imageBox-fadeBlocker${this.props.isHovering?.() ? "-hover" : ""}`}> + <img className="imageBox-fadeaway" key={"fadeaway"} + src={fadepath} + style={{ transform, transformOrigin }} draggable={false} + width={nativeWidth} /> + </div>} </div> {this.considerDownloadIcon} {this.considerGooglePhotosLink()} @@ -300,17 +344,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp </div>; } - // adjust y position to center image in panel aspect is bigger than image aspect. - // bcz :note, this is broken for rotated images - get ycenter() { - const { nativeWidth, nativeHeight } = this.nativeSize; - const rotation = NumCast(this.dataDoc[this.fieldKey + "-rotation"]); - const aspect = (rotation % 180) ? nativeWidth / nativeHeight : nativeHeight / nativeWidth; - return this.props.PanelHeight() / this.props.PanelWidth() > aspect ? - (this.props.PanelHeight() - this.props.PanelWidth() * aspect) / 2 : 0; - } - - screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, -this.ycenter); + screenToLocalTransform = this.props.ScreenToLocalTransform; contentFunc = () => [this.content]; private _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); @@ -377,6 +411,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp savedAnnotations={this._savedAnnotations} annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} + anchorMenuCrop={this.crop} />} </div >); } |