diff options
author | bob <bcz@cs.brown.edu> | 2019-09-25 11:03:11 -0400 |
---|---|---|
committer | bob <bcz@cs.brown.edu> | 2019-09-25 11:03:11 -0400 |
commit | b57741dbed846313e1b9d0dad3b6c8add2566277 (patch) | |
tree | 8922b014d31405fb6f3221cd4638f4104530b504 | |
parent | 1a12483b52c27259f0f2762d4369a79e1397af9c (diff) |
fixing up pdf rendering...
-rw-r--r-- | src/client/views/collections/CollectionPDFView.scss | 7 | ||||
-rw-r--r-- | src/client/views/collections/CollectionPDFView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.scss | 152 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 10 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 182 |
6 files changed, 130 insertions, 225 deletions
diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss index 50201bae8..a853e5ca6 100644 --- a/src/client/views/collections/CollectionPDFView.scss +++ b/src/client/views/collections/CollectionPDFView.scss @@ -29,12 +29,7 @@ top: 0; left: 0; z-index: -1; -} - -.collectionPdfView-cont-dragging { - span { - user-select: none; - } + overflow: hidden !important; } .collectionPdfView-backward { diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index 8eda4d9ee..8f052db3c 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -1,4 +1,4 @@ -import { computed } from "mobx"; +import { computed, trace } from "mobx"; import { observer } from "mobx-react"; import { Id } from "../../../new_fields/FieldSymbols"; import { emptyFunction } from "../../../Utils"; @@ -46,6 +46,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> { } render() { + trace(); return ( <CollectionBaseView {...this.props} className={"collectionPdfView-cont"} onContextMenu={this.onContextMenu}> {this.subView} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 9685f9bca..91037df7f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -99,6 +99,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF @observable _animPos: number[] | undefined = undefined; render() { + trace(); return ( <div className="collectionFreeFormDocumentView-container" style={{ diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index b55ca8ba5..cbea47e20 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -9,103 +9,101 @@ .pdfBox-cont { pointer-events: none; -} - -.pdfBox-cont-interactive { - pointer-events: all; - .pdfPage-textlayer { span { - pointer-events: all !important; - user-select: text; + pointer-events: none !important; + user-select: none; } } } -.pdfViewer-text { - .textLayer { - span { - user-select: text; +.pdfBox-cont-interactive { + pointer-events: all; + .pdfViewer-text { + .textLayer { + span { + user-select: text; + } } } +} - .react-pdf__Page { - transform-origin: left top; - position: absolute; - top: 0; - left: 0; - } +.react-pdf__Page { + transform-origin: left top; + position: absolute; + top: 0; + left: 0; +} - .react-pdf__Page__textContent span { - user-select: text; - } +.react-pdf__Page__textContent span { + user-select: text; +} - .react-pdf__Document { - position: absolute; - } +.react-pdf__Document { + position: absolute; +} - .pdfBox-settingsCont { - position: absolute; - right: 0; - top: 0; +.pdfBox-settingsCont { + position: absolute; + right: 0; + top: 0; + + .pdfBox-settingsButton { + border-bottom-left-radius: 50%; + display: flex; + justify-content: space-evenly; + align-items: center; + height: 70px; + background: none; + padding: 0; + + .pdfBox-settingsButton-arrow { + width: 0; + height: 0; + border-top: 25px solid transparent; + border-bottom: 25px solid transparent; + border-right: 25px solid #121721; + transition: all 0.5s; + } - .pdfBox-settingsButton { - border-bottom-left-radius: 50%; + .pdfBox-settingsButton-iconCont { + background: #121721; + height: 50px; + width: 70px; display: flex; - justify-content: space-evenly; + justify-content: center; align-items: center; - height: 70px; - background: none; - padding: 0; - - .pdfBox-settingsButton-arrow { - width: 0; - height: 0; - border-top: 25px solid transparent; - border-bottom: 25px solid transparent; - border-right: 25px solid #121721; - transition: all 0.5s; - } - - .pdfBox-settingsButton-iconCont { - background: #121721; - height: 50px; - width: 70px; - display: flex; - justify-content: center; - align-items: center; - margin-left: -2px; - border-radius: 3px; - } - } - - .pdfBox-settingsButton:hover { - background: none; + margin-left: -2px; + border-radius: 3px; } + } - .pdfBox-settingsFlyout { - width: 600px; - position: absolute; - background: #323232; - box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - left: -400px; - border-radius: 7px; - padding: 20px; - display: flex; - flex-direction: column; - font-size: 30px; - transition: all 0.5s; + .pdfBox-settingsButton:hover { + background: none; + } - .pdfBox-settingsFlyout-title { - color: white; - } + .pdfBox-settingsFlyout { + width: 600px; + position: absolute; + background: #323232; + box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); + left: -400px; + border-radius: 7px; + padding: 20px; + display: flex; + flex-direction: column; + font-size: 30px; + transition: all 0.5s; + + .pdfBox-settingsFlyout-title { + color: white; + } - .pdfBox-settingsFlyout-kvpInput { - margin-top: 20px; - display: grid; - grid-template-columns: 47.5% 5% 47.5%; - } + .pdfBox-settingsFlyout-kvpInput { + margin-top: 20px; + display: grid; + grid-template-columns: 47.5% 5% 47.5%; } } }
\ No newline at end of file diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 8471aefe0..a582ef2cc 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -176,10 +176,12 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (!(pdfUrl instanceof PdfField) || !this._pdf ? <div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> : - <div className={classname} - onScroll={this.onScroll} - style={{ marginTop: `${(this.Document.panY || 0)}px` }} - ref={this._mainCont}> + <div className={classname} onWheel={(e: React.WheelEvent) => e.stopPropagation()} onPointerDown={(e: React.PointerEvent) => { + let hit = document.elementFromPoint(e.clientX, e.clientY); + if (hit && hit.localName === "span") { + e.button === 0 && e.stopPropagation(); + } + }}> <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={this.Document.panY || 0} Document={this.props.Document} DataDoc={this.dataDoc} addDocTab={this.props.addDocTab} setPanY={this.setPanY} GoToPage={this.GotoPage} diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index c16cb7eb5..f8205a566 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -31,7 +31,6 @@ interface IViewerProps { fieldExtensionDoc: Doc; fieldKey: string; loaded: (nw: number, nh: number, np: number) => void; - panY: number; scrollTo: (y: number) => void; active: () => boolean; setPanY?: (n: number) => void; @@ -46,8 +45,6 @@ interface IViewerProps { */ @observer export class PDFViewer extends React.Component<IViewerProps> { - @observable.shallow private _visibleElements: JSX.Element[] = []; // _visibleElements is the array of JSX elements that gets rendered - @observable private _isPage: string[] = [];// _isPage is an array that tells us whether or not an index is rendered as a page or as a placeholder @observable private _pageSizes: { width: number, height: number }[] = []; @observable private _annotations: Doc[] = []; @observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>(); @@ -59,7 +56,7 @@ export class PDFViewer extends React.Component<IViewerProps> { @observable private _marqueeWidth: number = 0; @observable private _marqueeHeight: number = 0; - private _pageBuffer: number = 1; + private _resizeReaction: IReactionDisposer | undefined; private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef(); private _reactionDisposer?: IReactionDisposer; private _annotationReactionDisposer?: IReactionDisposer; @@ -67,8 +64,6 @@ export class PDFViewer extends React.Component<IViewerProps> { private _viewer: React.RefObject<HTMLDivElement> = React.createRef(); private _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); public _pdfViewer: any; - private _simpleLinkService: SimpleLinkService | undefined; - private _pdfFindController: any; private _searchString: string = ""; private _selectionText: string = ""; private _marquee: React.RefObject<HTMLDivElement> = React.createRef(); @@ -76,15 +71,6 @@ export class PDFViewer extends React.Component<IViewerProps> { private _startY: number = 0; private _startX: number = 0; - @computed get panY(): number { return this.props.panY; } - - // startIndex: where to start rendering pages - @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.panY) - this._pageBuffer); } - - // endIndex: where to end rendering pages - @computed get endIndex(): number { - return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.panY + (this._pageSizes[0] ? this._pageSizes[0].height : 0)) + this._pageBuffer); - } @computed get allAnnotations() { return DocListCast(this.props.fieldExtensionDoc.annotations).filter( @@ -95,25 +81,9 @@ export class PDFViewer extends React.Component<IViewerProps> { return this._annotations.filter(anno => this._script.run({ this: anno }, console.log, true).result); } - componentDidUpdate = (prevProps: IViewerProps) => { - if (this.panY !== prevProps.panY && this._simpleLinkService) { - let p = this.getPageFromScroll(this.panY); - for (let i = Math.max(0, p - 1); i <= Math.min(this.props.pdf.numPages - 1, p + 1); i++) { - this._pdfViewer._ensurePdfPageLoaded(this._pdfViewer._pages[i]).then(() => { - this._pdfViewer.renderingQueue.renderView(this._pdfViewer._pages[i]); - }); - } - } - } - componentDidMount = async () => { await this.initialLoad(); - // this._reactionDisposer = reaction( - // () => [this.props.active(), this.startIndex, this._pageSizes.length ? this.endIndex : 0], - // () => this.renderPages(), - // { fireImmediately: true }); - this._annotationReactionDisposer = reaction( () => this.props.fieldExtensionDoc && DocListCast(this.props.fieldExtensionDoc.annotations), annotations => annotations && annotations.length && this.renderAnnotations(annotations, true), @@ -138,9 +108,11 @@ export class PDFViewer extends React.Component<IViewerProps> { document.removeEventListener("copy", this.copy); document.addEventListener("copy", this.copy); + setTimeout(this.setupPdfJsViewer, 1000); } componentWillUnmount = () => { + this._resizeReaction && this._resizeReaction(); this._reactionDisposer && this._reactionDisposer(); this._annotationReactionDisposer && this._annotationReactionDisposer(); this._filterReactionDisposer && this._filterReactionDisposer(); @@ -166,44 +138,47 @@ export class PDFViewer extends React.Component<IViewerProps> { searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value; - pageLoaded = (page: Pdfjs.PDFPageViewport): void => this.props.loaded(page.width, page.height, this.props.pdf.numPages); - setSelectionText = (text: string) => this._selectionText = text; - getIndex = () => this.Index; - @action initialLoad = async () => { - this._pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages); - if (this._mainCont.current) { + if (this._pageSizes.length === 0) { + this._pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages); await Promise.all(this._pageSizes.map<Pdfjs.PDFPromise<any>>((val, i) => - this.props.pdf.getPage(i + 1).then((page: Pdfjs.PDFPageProxy) => { - runInAction(() => { - this._pageSizes.splice(i, 1, { - width: (page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]), - height: (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]) - }); + this.props.pdf.getPage(i + 1).then(action((page: Pdfjs.PDFPageProxy) => { + this._pageSizes.splice(i, 1, { + width: (page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]), + height: (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]) }); - }) - )); - this.props.loaded(Math.max(...this._pageSizes.map(i => i.width)), this._pageSizes[0].height, this.props.pdf.numPages); - this._simpleLinkService = new SimpleLinkService(this); - document.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = (this.props.Document[WidthSym]() / this._pageSizes[0].width)); - document.addEventListener("pagerendered", () => console.log("rendered")); - this._pdfViewer = new PDFJSViewer.PDFViewer({ - container: this._mainCont.current, - viewer: this._viewer.current, - linkService: this._simpleLinkService, - renderer: "svg" - }); - this._simpleLinkService.setPDFJSview(this._pdfViewer); - this._pdfViewer.setDocument(this.props.pdf); - this._pdfFindController = new PDFJSViewer.PDFFindController(this._pdfViewer); - this._pdfViewer.findController = this._pdfFindController; + i === this.props.pdf.numPages - 1 && this.props.loaded((page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]), + (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]), i); + })))); } } @action + setupPdfJsViewer = () => { + this._reactionDisposer = reaction(() => this.props.Document[WidthSym](), + () => this._pdfViewer.currentScaleValue = (this.props.Document[WidthSym]() / this._pageSizes[0].width)); + document.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = (this.props.Document[WidthSym]() / this._pageSizes[0].width)); + document.addEventListener("pagerendered", () => console.log("rendered")); + var pdfLinkService = new PDFJSViewer.PDFLinkService(); + let pdfFindController = new PDFJSViewer.PDFFindController({ + linkService: pdfLinkService, + }); + this._pdfViewer = new PDFJSViewer.PDFViewer({ + container: this._mainCont.current, + viewer: this._viewer.current, + linkService: pdfLinkService, + findController: pdfFindController, + renderer: "svg" + }); + pdfLinkService.setViewer(this._pdfViewer); + pdfLinkService.setDocument(this.props.pdf, null); + this._pdfViewer.setDocument(this.props.pdf); + } + + @action makeAnnotationDocument = (sourceDoc: Doc | undefined, color: string, createLink: boolean = true): Doc => { let mainAnnoDoc = Docs.Create.InstanceFromProto(new Doc(), "", {}); let mainAnnoDocProto = Doc.GetProto(mainAnnoDoc); @@ -336,7 +311,7 @@ export class PDFViewer extends React.Component<IViewerProps> { @action search = (searchString: string) => { if (this._pdfViewer._pageViewsReady) { - this._pdfFindController.executeCommand('findagain', { + this._pdfViewer.findController.executeCommand('findagain', { caseSensitive: false, findPrevious: undefined, highlightAll: true, @@ -346,7 +321,7 @@ export class PDFViewer extends React.Component<IViewerProps> { } else if (this._mainCont.current) { let executeFind = () => { - this._pdfFindController.executeCommand('find', { + this._pdfViewer.findController.executeCommand('find', { caseSensitive: false, findPrevious: undefined, highlightAll: true, @@ -364,27 +339,6 @@ export class PDFViewer extends React.Component<IViewerProps> { toggleSearch = (e: React.MouseEvent) => { e.stopPropagation(); this._searching = !this._searching; - - if (this._searching) { - if (!this._pdfFindController && this._mainCont.current && this._viewer.current && !this._pdfViewer) { - let simpleLinkService = new SimpleLinkService(this); - this._pdfViewer = new PDFJSViewer.PDFViewer({ - container: this._mainCont.current, - viewer: this._viewer.current, - linkService: simpleLinkService - }); - simpleLinkService.setPDFJSview(this._pdfViewer); - document.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = this.props.Document[WidthSym]() / this._pageSizes[0].width); - document.addEventListener("pagerendered", () => console.log("rendered")); - this._pdfViewer.setDocument(this.props.pdf); - this._pdfFindController = new PDFJSViewer.PDFFindController(this._pdfViewer); - this._pdfViewer.findController = this._pdfFindController; - } - } - } - @computed get visibleElementWrapper() { - trace(); - return this._visibleElements; } @action @@ -572,16 +526,10 @@ export class PDFViewer extends React.Component<IViewerProps> { render() { let scaling = this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width / this.props.Document[WidthSym]() : 1; - return (<div className="pdfViewer-viewer" ref={this._mainCont} onPointerDown={this.onPointerDown} onWheel={(e) => { - runInAction(() => { - if (e.currentTarget) { - this.props.Document.panTransformType = "None"; - this.props.Document.panY = e.currentTarget.scrollTop; - } - e.stopPropagation(); - }); - }}> - <div className="pdfViewer-text" ref={this._viewer} style={{ transform: `scale(${scaling})` }} /> + return (<div className="pdfViewer-viewer" ref={this._mainCont}> + <div className="pdfViewer-text" style={{ transform: `scale(${scaling})` }}> + <div key="viewerReal" ref={this._viewer} /> + </div> <div className="pdfPage-dragAnnotationBox" ref={this._marquee} style={{ left: `${this._marqueeX}px`, top: `${this._marqueeY}px`, @@ -594,7 +542,7 @@ export class PDFViewer extends React.Component<IViewerProps> { <Annotation {...this.props} anno={anno} key={`${anno[Id]}-annotation`} />)} </div> <div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()} - style={{ bottom: -this.props.panY, left: `${this._searching ? 0 : 100}%` }}> + style={{ bottom: 0, left: `${this._searching ? 0 : 100}%` }}> <button className="pdfViewer-overlayButton" title="Open Search Bar" /> <input className="pdfViewer-overlaySearchBar" placeholder="Search" onChange={this.searchStringChanged} onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} /> @@ -602,17 +550,17 @@ export class PDFViewer extends React.Component<IViewerProps> { <FontAwesomeIcon icon="search" size="3x" color="white" /></button> </div> <button className="pdfViewer-overlayButton" onClick={this.prevAnnotation} title="Previous Annotation" - style={{ bottom: -this.props.panY + 280, right: 10, display: this.props.active() ? "flex" : "none" }}> + style={{ bottom: 280, right: 10, display: this.props.active() ? "flex" : "none" }}> <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}> <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="3x" /></div> </button> <button className="pdfViewer-overlayButton" onClick={this.nextAnnotation} title="Next Annotation" - style={{ bottom: -this.props.panY + 200, right: 10, display: this.props.active() ? "flex" : "none" }}> + style={{ bottom: 200, right: 10, display: this.props.active() ? "flex" : "none" }}> <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}> <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="3x" /></div> </button> <button className="pdfViewer-overlayButton" onClick={this.toggleSearch} title="Open Search Bar" - style={{ bottom: -this.props.panY + 10, right: 0, display: this.props.active() ? "flex" : "none" }}> + style={{ bottom: 10, right: 0, display: this.props.active() ? "flex" : "none" }}> <div className="pdfViewer-overlayButton-arrow" onPointerDown={(e) => e.stopPropagation()}></div> <div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}> <FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="3x" /></div> @@ -621,44 +569,4 @@ export class PDFViewer extends React.Component<IViewerProps> { } } -export enum AnnotationTypes { Region } - -class SimpleLinkService { - _viewer: PDFViewer; - _pdfjsView: any; - - constructor(viewer: PDFViewer) { - this._viewer = viewer; - } - setPDFJSview(v: any) { this._pdfjsView = v; } - - navigateTo() { } - - getDestinationHash() { return "#"; } - - getAnchorUrl() { return "#"; } - - setHash() { } - - isPageVisible(page: number) { return true; } - - executeNamedAction() { } - - cachePageRef() { } - - get pagesCount() { return this._viewer._pdfViewer.pagesCount; } - - get page() { return this._viewer.getPageFromScroll(NumCast(this._viewer.props.panY)) + 1; } - set page(p: number) { - this._pdfjsView._ensurePdfPageLoaded(this._pdfjsView._pages[p - 1]).then(() => { - this._pdfjsView.renderingQueue.renderView(this._pdfjsView._pages[p - 1]); - if (this._viewer.props.GoToPage) { - this._viewer.props.GoToPage(p); - } - }); - } - - - get rotation() { return 0; } - set rotation(value: any) { } -}
\ No newline at end of file +export enum AnnotationTypes { Region }
\ No newline at end of file |