UNPKG

ngx-extended-pdf-viewer

Version:

Embedding PDF files in your Angular application. Highly configurable viewer including the toolbar, sidebar, and all the features you're used to.

996 lines 178 kB
export class RelativeCoordsSupport { constructor(_zone, component, options) { this._zone = _zone; this.component = component; this.options = { debug: false, moveEnabled: true, disableEventHandling: false, }; this.startX = 0; this.startY = 0; this.moveX = 0; this.moveY = 0; this.startLeft = 0; this.startTop = 0; this.state = "idle"; this.initialPinchDistance = 0; this.currentScale = 1.0; this.pointEnd = {}; this.debug = { enabled: false, nf: new Intl.NumberFormat('en-US', { style: 'decimal', maximumFractionDigits: 2 }), x: 0, y: 0 }; options = options || {}; Object.keys(this.options).forEach(attribut => { if (options[attribut] === undefined) options[attribut] = this.options[attribut]; }); this.options = options; this.debug.enabled = this.options.debug; if (this.debug.enabled) console.log("RelativeCoordsSupport.constructor"); this.boundOnViewerTouchStart = this.onViewerTouchStart.bind(this); this.boundOnViewerTouchMove = this.onViewerTouchMove.bind(this); this.boundOnViewerTouchEnd = this.onViewerTouchEnd.bind(this); this.boundOnViewerMouseDown = this.onViewerMouseDown.bind(this); this.boundOnViewerMouseMove = this.onViewerMouseMove.bind(this); this.boundOnViewerMouseUp = this.onViewerMouseUp.bind(this); this.boundOnViewerWheel = this.onViewerWheel.bind(this); this.initializeRelativeCoords(); } isMobile() { return (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0); // ('ontouchstart' in window) || } onViewerTouchStart(event) { if (this.options.disableEventHandling) return; this.initialPinchDistance = 0; if (event.touches.length === 2) { const container = document.getElementById('viewerContainer'); const rect = container.getBoundingClientRect(); if (event.touches[0].pageX >= rect.left && event.touches[0].pageX <= rect.right) { if (event.touches[0].pageY >= (rect.top + window.scrollY) && event.touches[0].pageY <= (rect.bottom + window.scrollY)) { if (event.touches[1].pageX >= rect.left && event.touches[1].pageX <= rect.right) { if (event.touches[1].pageY >= (rect.top + window.scrollY) && event.touches[1].pageY <= (rect.bottom + window.scrollY)) { this.startX = (event.touches[0].pageX + event.touches[1].pageX) / 2; this.startY = (event.touches[0].pageY + event.touches[1].pageY) / 2; this.initialPinchDistance = Math.hypot(event.touches[1].pageX - event.touches[0].pageX, event.touches[1].pageY - event.touches[0].pageY); this.startLeft = parseFloat(getComputedStyle(this.viewer).left) || 0; this.startTop = parseFloat(getComputedStyle(this.viewer).top) || 0; this.state = "zoom"; if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } } } } } if (event.touches.length === 1) { let touch = event.touches[0]; if (this.options.moveEnabled && this.isInsideContainer([touch]) && this.state == "idle") { const viewerContainer = document.getElementById('viewerContainer'); const rect = viewerContainer.getBoundingClientRect(); let pageX = touch.pageX - rect.left; let pageY = touch.pageY - rect.top; if (this.debug.enabled) this.debugPoint(pageX, pageY); this.startX = pageX; this.startY = pageY; let left = parseFloat(getComputedStyle(this.viewer).left) || 0; let top = parseFloat(getComputedStyle(this.viewer).top) || 0; if (this.debug.enabled) { console.log("TouchStart: " + this.debug.nf.format(pageX) + " / " + this.debug.nf.format(pageY) + ", startX/Y: " + this.debug.nf.format(this.startX) + " / " + this.debug.nf.format(this.startY) + ", startLeft/Top: " + this.debug.nf.format(this.startLeft) + " -> " + this.debug.nf.format(left) + " / " + this.debug.nf.format(this.startTop) + " -> " + this.debug.nf.format(top) + ", state: " + this.state, ", dims: ", this.getDimensions(this.viewer)); } this.startLeft = left; this.startTop = top; this.state = "move"; if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } else { // console.log("TouchStart: isInside: " + this.isInsideContainer([ touch ]) + ", state: " + this.state); } } } // private getCurrentPagesInView():number[] { // const PDFViewerApplication: any = (window as any).PDFViewerApplication; // let page = PDFViewerApplication.page; // let pageCount = PDFViewerApplication.pdfViewer._pages.length; // let spreadMode = PDFViewerApplication.pdfViewer.spreadMode as SpreadModeType; // let pages = [ page ]; // if (page == 1) return pages; // let isSpread = spreadMode == SpreadModeType.EVEN || SpreadModeType.ODD; // // console.log("isSpread: " + isSpread+ ", pages: " + pages.join(",")); // if (!isSpread) return pages; // if (page % 2 == 1) { // page--; // pages = [ page ]; // } // // if (page % 2 == 1) // let nextPage = page + 1; // if (nextPage <= pageCount) pages.push(nextPage); // // console.log("nextPage: " + nextPage + ", pageCount: " + pageCount+ ", pages: " + pages.join(",")); // return pages; // } debugPoint(x, y, viewer = false) { if (!this.options.debugPoint) return; const viewerContainer = document.getElementById('viewerContainer'); let id = 'debug-point' + (viewer ? "-viewer" : ""); let point = document.getElementById(id); let size = viewer ? 10 : 5; if (!point) { point = document.createElement("div"); point.id = id; point.style.position = "absolute"; point.style.width = size + "px"; point.style.height = size + "px"; point.style.borderRadius = "100px"; point.style.backgroundColor = viewer ? "red" : "blue"; if (!viewer) viewerContainer.appendChild(point); else this.viewer.appendChild(point); } let dims = this.getDimensions(this.viewer); if (viewer) { // this.debug.xv = x; // this.debug.yv = y; // console.log("debugPoint.viewer: " + this.debug.nf.format(x) + " / " + this.debug.nf.format(y) + ", | " + this.debug.nf.format(x / dims.elem.width * 100) + " % / " + this.debug.nf.format(y / dims.elem.height * 100) + " %, dims: ", dims.elem); // let vts = this.getViewerTransformScale(); // if(vts != 1.0) { // x /= vts; // y /= vts; // console.log("debugPoint.viewer: " + this.debug.nf.format(x) + " / " + this.debug.nf.format(y)); // } } else { this.debug.x = x; this.debug.y = y; // console.log("debugPoint.cont: " + this.debug.nf.format(x) + " / " + this.debug.nf.format(y) + " | " + this.debug.nf.format(x / dims.parent.width * 100) + " % / " + this.debug.nf.format(y / dims.parent.height * 100) + " %, dims: ", dims.parent); } point.style.left = (x - (size / 2)) + "px"; point.style.top = (y - (size / 2)) + "px"; } onViewerTouchMove(event) { if (this.options.disableEventHandling) return; const PDFViewerApplicationOptions = window.PDFViewerApplicationOptions; const PDFViewerApplication = window.PDFViewerApplication; const viewerContainer = document.getElementById('viewerContainer'); const rect = viewerContainer.getBoundingClientRect(); const vr = this.viewer.getBoundingClientRect(); if (this.initialPinchDistance <= 0 || event.touches.length !== 2) { if (event.touches.length == 1 && this.state == "move") { const touch = event.touches[0]; let pageX = touch.pageX - rect.left + viewerContainer.scrollLeft; let pageY = touch.pageY - rect.top + viewerContainer.scrollTop; if (this.debug.enabled) this.debugPoint(pageX, pageY); let diffX = pageX - this.startX; let diffY = pageY - this.startY; let left = this.startLeft + diffX; let top = this.startTop + diffY; let constrain = this.constrain({ left: left, top: top }); left = constrain.left; top = constrain.top; if (this.debug.enabled) { console.log("TouchMove: " + this.debug.nf.format(pageX) + " / " + this.debug.nf.format(pageY) + ", startX/Y: " + this.debug.nf.format(this.startX) + " / " + this.debug.nf.format(this.startY) + ", diff: " + this.debug.nf.format(diffX) + " / " + this.debug.nf.format(diffY) + ", l/t: " + this.debug.nf.format(left) + " / " + this.debug.nf.format(top) + ", viewer.w/h: " + this.debug.nf.format(vr.width) + " / " + this.debug.nf.format(vr.height)); } this.viewer.style.left = left + "px"; this.viewer.style.top = top + "px"; if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } return; } const pinchDistance = Math.hypot(event.touches[1].pageX - event.touches[0].pageX, event.touches[1].pageY - event.touches[0].pageY); // const container = document.getElementById('viewerContainer') as HTMLDivElement; // const containerRect = container.getBoundingClientRect(); let pageX = (event.touches[1].pageX + event.touches[0].pageX) / 2; let pageY = (event.touches[1].pageY + event.touches[0].pageY) / 2; this.moveX = pageX; this.moveY = pageY; let dims = this.getDimensions(this.viewer, { pageX: pageX, pageY: pageY }); // //const viewerRect = this.viewer.getBoundingClientRect(); // pageX -= rect.left; // pageY -= rect.top; // pageX -= vr.left; // pageY -= vr.top; // pageX = dims.scaled.width * dims.point.v.xp; // pageY = dims.scaled.height * dims.point.v.yp; // let originX = pageX; // + viewerContainer.scrollLeft; // this.startX + container.scrollLeft; // let originY = pageY; // + viewerContainer.scrollTop ; //this.startY + container.scrollTop; const originX = dims.scaled.width * dims.point.v.xp; const originY = dims.scaled.height * dims.point.v.yp; if (this.debug.enabled) this.debugPoint(this.moveX - rect.left, this.moveY - rect.top); let prevScale = this.currentScale; this.currentScale = pinchDistance / this.initialPinchDistance; let minZoom = Number(PDFViewerApplicationOptions.get('minZoom')); if (!minZoom) { minZoom = 0.1; } const currentZoom = PDFViewerApplication.pdfViewer._currentScale; if (currentZoom * this.currentScale < minZoom) { this.currentScale = minZoom / currentZoom; } let maxZoom = Number(PDFViewerApplicationOptions.get('maxZoom')); if (!maxZoom) { maxZoom = 10; } if (currentZoom * this.currentScale > maxZoom) { this.currentScale = maxZoom / currentZoom; } if (this.debug.enabled) { console.log("TouchMove PINCH: " + ", startX/Y: " + this.debug.nf.format(this.startX) + " / " + this.debug.nf.format(this.startY) + ", moveX/Y: " + +this.debug.nf.format(this.moveX) + " / " + this.debug.nf.format(this.moveY) + ", rect.l/t: " + this.debug.nf.format(rect.left) + " / " + this.debug.nf.format(rect.top) + ", viewer.l/t: " + this.debug.nf.format(vr.left) + " / " + this.debug.nf.format(vr.top) // + ", viewerContainer.sl/st: " + this.debug.nf.format(viewerContainer.scrollLeft) + " / " + this.debug.nf.format(viewerContainer.scrollTop) + ", originX/Y: " + this.debug.nf.format(originX) + " / " + this.debug.nf.format(originY) + ", viewer.w/h: " + this.debug.nf.format(vr.width) + " / " + this.debug.nf.format(vr.height) + ", currentScale: " + this.debug.nf.format(prevScale) + " -> " + this.debug.nf.format(this.currentScale) + ", dims: ", dims); } this.viewer.style.transform = `scale(${this.currentScale})`; this.viewer.style.transformOrigin = `${originX}px ${originY}px`; // this.transformScale = this.currentScale; if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } onViewerTouchEnd(event) { if (this.options.disableEventHandling) return; if (this.debug.enabled) console.log("onViewerTouchEnd" + ", vts: " + this.getViewerTransformScale("onViewerTouchEnd") + ', state: ' + this.state + ", initialPinchDistance: " + this.initialPinchDistance); const PDFViewerApplication = window.PDFViewerApplication; // let to = this.viewer.style.transformOrigin; // this.viewer.style.transform = `none`; // this.viewer.style.transformOrigin = `unset`; let dimsStart = this.getDimensions(this.viewer); let tl = event.changedTouches.length; let pageX = this.moveX; let pageY = this.moveY; if (tl > 1) { pageX = (event.changedTouches[1].pageX + event.changedTouches[0].pageX) / 2; pageY = (event.changedTouches[1].pageY + event.changedTouches[0].pageY) / 2; } else { if (this.debug.enabled) console.log("end.moveX/Y: " + this.moveX + " -> " + pageX + ", moveY: " + this.moveY + " -> " + pageY + ", tl: " + tl); } // this.currentScale = 1; let now = new Date().getTime(); if (this.pointEnd.time) { let pe = this.pointEnd; let diff = now - pe.time; // console.log("pointEnd.diff: " + diff); if (pe.pageX == pageX && pe.pageY == pageY && diff < 300) { let PDFViewerApplication = window.PDFViewerApplication; let currentScale = PDFViewerApplication.pdfViewer.currentScale; let scaleFactor = 1.4; let newScale = this.isZooming() ? (currentScale / scaleFactor) : (currentScale * scaleFactor); // let newScale = currentScale * 1.2; // if (this.debug.enabled) console.log("pointEnd.point mateches, new scale: " + newScale); if (this.initialPinchDistance <= 0 || this.state == "move") { if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } setTimeout(() => { this.setViewerScale(newScale); this.pointEnd = {}; }, 5); return; } } this.pointEnd = { time: now, pageX: pageX, pageY: pageY }; if (this.state == "move") { this.resetPinchZoomParams(); return; } if (this.initialPinchDistance <= 0) { this.resetPinchZoomParams(); return; } let currentScale = PDFViewerApplication.pdfViewer.currentScale; let newScale = currentScale * this.currentScale; // let scaleChange = 1 + (newScale - currentScale) / currentScale; const container = document.getElementById('viewerContainer'); const rect = container.getBoundingClientRect(); const viewerRect = this.viewer.getBoundingClientRect(); let dims = this.getDimensions(this.viewer); if (this.debug.enabled) this.debugPoint(pageX, pageY); if (this.debug.enabled) { console.log("TouchEnd: " + ", scale: " + this.debug.nf.format(currentScale) + " -> " + this.debug.nf.format(newScale) + ", cs: " + this.currentScale + ", pageX/Y: " + this.debug.nf.format(pageX) + " / " + this.debug.nf.format(pageY) + ", startX/Y: " + this.debug.nf.format(this.startX) + " / " + this.debug.nf.format(this.startY) // + ", diff: " + this.debug.nf.format(diffX) + " / " + this.debug.nf.format(diffY) // + ", diffs: " + this.debug.nf.format(diffXs) + " / " + this.debug.nf.format(diffYs) // + ", l/t: " + this.debug.nf.format(viewerRect.left) + " -> " +this.debug.nf.format(left) + " / " + this.debug.nf.format(viewerRect.top) + " -> " +this.debug.nf.format(top) + ", viewer.w/h: " + this.debug.nf.format(viewerRect.width) + " / " + this.debug.nf.format(viewerRect.height) + ", dims: ", dims); } this.setViewerScale(newScale, { resetTransform: true }); this.resetPinchZoomParams(); // }, 50); if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); // if (tl == 1) { // let pageX = event.changedTouches[0].pageX; // let pageY = event.changedTouches[0].pageY; // } } onViewerMouseDown(event) { if (this.options.disableEventHandling) return; let isInside = this.isInsideContainer([event]); if (!isInside) return; if (!this.options.moveEnabled) return; let dims = this.getDimensions(this.viewer, event); // this.zoomToPoint(event, event.pageX, event.pageY); if (this.debug.enabled) { this.debugPoint(dims.point.c.x, dims.point.c.y); this.debugPoint(dims.point.v.x, dims.point.v.x, true); } this.startX = dims.point.c.x; this.startY = dims.point.c.y; this.startLeft = parseFloat(getComputedStyle(this.viewer).left) || 0; this.startTop = parseFloat(getComputedStyle(this.viewer).top) || 0; this.state = "move"; if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } onViewerMouseMove(event) { if (this.options.disableEventHandling) return; if (this.state != "move") { // console.log("mousemove: state!=move: " + this.state); return; } let dims = this.getDimensions(this.viewer, event); if (this.debug.enabled) this.debugPoint(dims.point.c.x, dims.point.c.y); let diffX = dims.point.c.x - this.startX; let diffY = dims.point.c.y - this.startY; let left = this.startLeft + diffX; let top = this.startTop + diffY; let constrain = this.constrain({ left: left, top: top }); left = constrain.left; top = constrain.top; this.viewer.style.left = left + "px"; this.viewer.style.top = top + "px"; if (this.debug.enabled) { console.log("mousemove: " + this.debug.nf.format(dims.point.c.x) + " / " + this.debug.nf.format(dims.point.c.y) + ", diff: " + this.debug.nf.format(diffX) + " / " + this.debug.nf.format(diffY) + ", l/t: " + this.debug.nf.format(left) + " / " + this.debug.nf.format(top)); } if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); } onViewerMouseUp(event) { if (this.options.disableEventHandling) return; let isInside = this.isInsideContainer([event]); if (this.debug.enabled) console.log("mouseup: " + this.debug.nf.format(event.pageX) + " / " + this.debug.nf.format(event.pageY) + "; inside: " + isInside); // document.removeEventListener("mousemove", event); if (!isInside) return; this.resetPinchZoomParams(); //TODO: kan ikke bruke preventDefault hvis vi skal kunne støtte dobbeltklikk if (event.cancelable) { event.preventDefault(); } event.stopPropagation(); let pageX = event.pageX; let pageY = event.pageY; let now = new Date().getTime(); if (this.pointEnd.time) { let pe = this.pointEnd; let diff = now - pe.time; // console.log("pointEnd.diff: " + diff); if (pe.pageX == pageX && pe.pageY == pageY && diff < 300) { let PDFViewerApplication = window.PDFViewerApplication; let currentScale = PDFViewerApplication.pdfViewer.currentScale; let scaleFactor = 1.4; let newScale = this.isZooming() ? (currentScale / scaleFactor) : (currentScale * scaleFactor); // if (this.debug.enabled) console.log("pointEnd.point mateches, isZ: "+this.isZooming() +", new scale: " + currentScale + " -> " + newScale); setTimeout(() => { this.setViewerScale(newScale); this.pointEnd = {}; }, 5); return; } } this.pointEnd = { time: now, pageX: pageX, pageY: pageY }; // console.log("updateing pointEnd: ", this.pointEnd); } resetPinchZoomParams() { this.startX = this.startY = this.moveX = this.moveY = this.startLeft = this.startTop = this.initialPinchDistance = 0; this.currentScale = 1; this.state = "idle"; } getBoxStyle(elem, name, style = window.getComputedStyle(elem)) { const suffix = name === 'border' ? 'Width' : ''; return { left: parseFloat(style[`${name}Left${suffix}`]) || 0, right: parseFloat(style[`${name}Right${suffix}`]) || 0, top: parseFloat(style[`${name}Top${suffix}`]) || 0, bottom: parseFloat(style[`${name}Bottom${suffix}`]) || 0, }; } getDimensions(elem, point) { const parent = elem.parentNode; const style = window.getComputedStyle(elem); const parentStyle = window.getComputedStyle(parent); const rectElem = elem.getBoundingClientRect(); const rectParent = parent.getBoundingClientRect(); const vts = this.getViewerTransformScale("getDimensions"); const vto = this.getViewerTransformOrigin(); let res = { elem: { style, width: rectElem.width, height: rectElem.height, top: rectElem.top, bottom: rectElem.bottom, left: rectElem.left, right: rectElem.right, margin: this.getBoxStyle(elem, 'margin', style), border: this.getBoxStyle(elem, 'border', style) }, rel: { width: rectElem.width, height: rectElem.height, top: rectElem.top - rectParent.top, left: rectElem.left - rectParent.left, bottom: rectElem.bottom - rectParent.top, right: rectElem.right - rectParent.left, }, parent: { style: parentStyle, width: rectParent.width, height: rectParent.height, top: rectParent.top, bottom: rectParent.bottom, left: rectParent.left, right: rectParent.right, padding: this.getBoxStyle(parent, 'padding', parentStyle), border: this.getBoxStyle(parent, 'border', parentStyle) } }; if (vts == 1.0) res.scaled = res.rel; else { let sw = res.rel.width / vts; let sh = res.rel.height / vts; let wd = res.rel.width - sw; // 118 let hd = res.rel.height - sh; res.scaled = { vts: vts, vto: vto, width: sw, height: sh, left: res.rel.left + wd / 2, right: res.rel.right - wd / 2, top: res.rel.top + hd / 2, bottom: res.rel.bottom - hd / 2, wd: wd, hd: hd, }; } let vx = point ? point.pageX - rectElem.left : rectElem.width / 2; let vy = point ? point.pageY - rectElem.top : rectElem.height / 2; let cx = point ? point.pageX - rectParent.left : vx + res.rel.left; let cy = point ? point.pageY - rectParent.top : vy + res.rel.top; let vxp = vx / rectElem.width; let vyp = vy / rectElem.height; let cxp = cx / rectParent.width; let cyp = cy / rectParent.height; res.point = { src: point, v: { x: vx, y: vy, xp: vxp, yp: vyp }, c: { x: cx, y: cy, xp: cxp, yp: cyp } }; return res; } // return res; // } getDimDiff(start, end) { // let se = start.elem; // let ee = end.elem; // let sp = start.parent; // let ep = end.parent; let input = { elem: { start: start.elem, end: end.elem }, parent: { start: start.parent, end: end.parent }, rel: { start: start.rel, end: end.rel }, scaled: { start: start.scaled, end: end.scaled }, }; let res = {}; for (let type of ["elem", "parent", "rel", "scaled"]) { let s = input[type].start; let e = input[type].end; res[type] = {}; for (let prop of ["width", "height", "top", "bottom", "left", "right"]) { let sv = s[prop]; let ev = e[prop]; let diff = ev - sv; res[type][prop + "Label"] = this.debug.nf.format(sv) + " -> " + this.debug.nf.format(ev) + ", diff: " + this.debug.nf.format(diff) + " (" + this.debug.nf.format(diff / sv * 100.0) + " %)"; res[type][prop] = diff; } } return res; } constrain(p) { const dims = this.getDimensions(this.viewer); let isScaled = dims.scaled.vts !== undefined && dims.scaled.vts != 1.0; let minX = p.left, maxX = p.left, minY = p.top, maxY = p.top; if (dims.elem.width <= dims.parent.width) { // inside minX = 0; maxX = (dims.parent.width - dims.elem.width); } else { // outside minX = -(dims.elem.width - dims.parent.width); maxX = 0; } if (dims.elem.height <= dims.parent.height) { // inside minY = 0; maxY = (dims.parent.height - dims.elem.height); } else { // outside minY = -(dims.elem.height - dims.parent.height); maxY = 0; } if (isScaled) { let vto = dims.scaled.vto; let xp = vto ? vto.x / dims.scaled.width : 0.5; let yp = vto ? vto.y / dims.scaled.height : 0.5; minX += dims.scaled.wd * xp; maxX += dims.scaled.wd * xp; minY += dims.scaled.hd * yp; maxY += dims.scaled.hd * yp; } let cLeft = Math.max(Math.min(p.left, maxX), minX); let cTop = Math.max(Math.min(p.top, maxY), minY); // if (this.debug.enabled) console.log("constrain, left: " + p.left + " -> " + cLeft + " ("+minX + "-"+maxX+")" + ", top: " + p.top + " -> " + cTop + " ("+minY + "-"+maxY+"), dims: ", dims); return { left: cLeft, top: cTop }; } isInsideContainer(points) { const viewerContainer = document.getElementById('viewerContainer'); const rect = viewerContainer.getBoundingClientRect(); if (points === undefined || points.length == 0) return false; //TODO: Check event, is target.parent the viewerContainer? // let allInside = true; for (let point of points) { let target = point.target; if (target) { let closest = target.closest("#viewerContainer"); // console.log("closest: ", closest) if (closest == undefined) { return false; } } let pageX = point.pageX; // + viewerContainer.scrollLeft; let pageY = point.pageY; // + viewerContainer.scrollTop; let inside = false; if (pageX >= rect.left && pageX <= rect.right) { if (pageY >= (rect.top + window.scrollY) && pageY <= (rect.bottom + window.scrollY)) { inside = true; } } // console.log("pageX/Y: " + pageX + " / " + pageY + ", inside: " + inside + "; rect: ", rect, ", point: ", point); if (!inside) return false; } return true; } getViewerTransformScale(src) { let tf = getComputedStyle(this.viewer).transform; if (tf == "none" || tf.indexOf("(") < 0) { let vts = 1.0; // if (this.transformScale > 0.0) { // vts = this.transformScale // } // if (this.debug.enabled) console.log("getViewerTransformScale, tf: " + tf + ", indexOf (: " + tf.indexOf("(") + ", src: " + src + ", vts: " + vts); return vts; } let isScale = tf.indexOf("scale") >= 0; let transformScale = parseFloat(tf.substring(tf.indexOf("(") + 1, tf.indexOf(isScale ? ")" : ","))); // if (this.debug.enabled) console.log("getViewerTransformScale, tf: " + tf + ", indexOf (: " + tf.indexOf("(") + ", transformScale: " + transformScale + ", src: " + src); return transformScale; } getViewerTransformOrigin() { let to = this.viewer.style.transformOrigin; if (to == undefined || to == "unset") return undefined; let parts = to.split(" "); if (parts.length != 2) return undefined; return { x: parseFloat(parts[0]), y: parseFloat(parts[1]) }; } checkContraint() { const dims = this.getDimensions(this.viewer); let constrain = this.constrain({ left: dims.elem.left, top: dims.elem.top }); return constrain.left != dims.elem.left && constrain.top != dims.elem.top; } updateViewerPosition(forceUpdate = false) { let viewerContainer = document.getElementById('viewerContainer'); this.viewer = document.getElementById('viewer'); const dims = this.getDimensions(this.viewer); let constrain = this.constrain({ left: dims.elem.left, top: dims.elem.top }); // ; let transformScale = this.getViewerTransformScale("updateViewerPosition"); // if (transformScale == 1.0) if (this.debug.enabled) { // console.log("updateViewerPosition" // + ", updateLeft: " + (dims.elem.width <= dims.parent.width) // + ", updateTop: " + (dims.elem.height <= dims.parent.height) // + ", checkContraint: " + this.checkContraint() // + ", transformScale: " + transformScale // + ", dims: ", dims); } let point = { left: undefined, top: undefined }; if (forceUpdate || dims.elem.width <= dims.parent.width || (constrain && constrain.left != dims.elem.left)) { let left = (dims.parent.width - (dims.elem.width / transformScale)) / 2; // console.log("updateViewerPosition, left: " + this.viewer.style.left + " -> " + left); // this.viewer.style.left = left + "px"; point.left = left; } if (forceUpdate || dims.elem.height <= dims.parent.height || (constrain && constrain.top != dims.elem.top)) { let top = (dims.parent.height - (dims.elem.height / transformScale)) / 2; // console.log("updateViewerPosition, top: " + this.viewer.style.top + " -> " + top); // this.viewer.style.top = top + "px"; point.top = top; } if (point.left || point.top) { this.viewer.style.left = point.left + "px"; this.viewer.style.top = point.top + "px"; } } setViewerScale(newScale, options = {}) { let vtsSource = getComputedStyle(this.viewer).transform; if (this.debug.enabled) console.log("setViewerScale, newScale: " + newScale + ", vtsSource: " + vtsSource); let origin = options.origin; // let resetTransform = options.resetTransform === undefined || options.resetTransform === true; let vts = this.getViewerTransformScale("setViewerScale"); let dims = this.getDimensions(this.viewer); // let dimsAfterTransformReset = dims; let reset = { left: undefined, top: undefined }; if (vts != 1.0) { // resetTransform && if (vtsSource != "none") { reset.left = dims.rel.left; reset.top = dims.rel.top; } this.viewer.style.transform = 'none'; this.viewer.style.transformOrigin = 'unset'; // this.transformScale = -1; // dimsAfterTransformReset = this.getDimensions(this.viewer); } let PDFViewerApplication = window.PDFViewerApplication; let currentScale = PDFViewerApplication.pdfViewer.currentScale; if (origin == undefined) { origin = { x: dims.elem.width / 2, y: dims.elem.height / 2 }; } let oxp = origin.x / dims.elem.width; let oyp = origin.y / dims.elem.height; if (this.debug.enabled) { console.log("setViewerScale, currentScale: " + this.debug.nf.format(currentScale) + " -> " + this.debug.nf.format(newScale) + ", vts: " + this.debug.nf.format(vts) + " (" + vtsSource + ")" + ", origin: " + this.debug.nf.format(origin.x) + " (" + this.debug.nf.format(oxp * 100) + ") / " + this.debug.nf.format(origin.y) + " (" + this.debug.nf.format(oyp * 100) + ")" + ", debug.x/Y: " + this.debug.nf.format(this.debug.x) + " / " + +this.debug.nf.format(this.debug.y) + ", isZooming: " + this.isZooming() + ", dims: ", dims); } PDFViewerApplication.pdfViewer._setScale(newScale, true); let dimsAfter = this.getDimensions(this.viewer); let dimDiff = this.getDimDiff(dims, dimsAfter); let dimsCorr = { left: parseFloat(getComputedStyle(this.viewer).left) || 0, top: parseFloat(getComputedStyle(this.viewer).top) || 0, }; dimsCorr.leftDiff = -(dimDiff.elem.width * oxp); dimsCorr.topDiff = -(dimDiff.elem.height * oyp); dimsCorr.leftNext = dimsCorr.left + dimsCorr.leftDiff; dimsCorr.topNext = dimsCorr.top + dimsCorr.topDiff; if (reset.left) { if (this.debug.enabled) { console.log("dimsCorr.leftNext: " + this.debug.nf.format(dimsCorr.leftNext) + " -> " + this.debug.nf.format(reset.left)); console.log("dimsCorr.topNext: " + this.debug.nf.format(dimsCorr.topNext) + " -> " + this.debug.nf.format(reset.top)); } dimsCorr.leftNext = reset.left; dimsCorr.topNext = reset.top; } this.viewer.style.left = dimsCorr.leftNext + "px"; this.viewer.style.top = dimsCorr.topNext + "px"; if (this.debug.enabled) { console.log("setViewerScale2, newCurrentScale: " + this.debug.nf.format(PDFViewerApplication.pdfViewer.currentScale) + ", isZooming: " + this.isZooming() + ", dimsAfter: ", dimsAfter, ", dimDiff: ", dimDiff, ", dimsCorr: ", dimsCorr); } } isZooming() { let PDFViewerApplication = window.PDFViewerApplication; const PDFViewerApplicationOptions = window.PDFViewerApplicationOptions; let currentScale = PDFViewerApplication.pdfViewer.currentScale; let czf = Math.round(currentScale * 10000); let minZoom = Math.round(Number(PDFViewerApplicationOptions.get('minZoom')) * 10000); // console.log("isZooming, czf: " + czf + ", minZoom: " + minZoom + "; isZ: " + (czf > minZoom)); return czf > minZoom; } onViewerWheel(event) { if (this.options.disableEventHandling) return; if (this.debug.enabled) console.log("onWheel: event: ", event); setTimeout(() => { this.updateViewerPosition(); }, 2); } ; initializeRelativeCoords() { let viewerContainer = document.getElementById('viewerContainer'); this.viewer = document.getElementById('viewer'); this.component.root.nativeElement.classList.add("relative-coords"); let stfItemHack = document.createElement("div"); stfItemHack.classList.add("stf__item"); viewerContainer.appendChild(stfItemHack); if (this.debug.enabled) console.log("initializeRelativeCoords: isMobile: " + this.isMobile()); let onContainerScoll = (event) => { //console.log("onContainerScoll: l/t: " + viewerContainer.scrollLeft + " / " + viewerContainer.scrollTop + ", event: " , event); if (viewerContainer.scrollLeft != 0 || viewerContainer.scrollTop != 0) viewerContainer.scroll({ left: 0, top: 0 }); }; viewerContainer.addEventListener('scroll', onContainerScoll); this.component.pagesLoaded.subscribe(async (event) => { if (this.debug.enabled) console.log("initializeRelativeCoords: scrollTop: ", viewerContainer.scrollTop); setTimeout(() => { // console.log("pageChange: pages: ", this.getCurrentPagesInView()) this.updateViewerPosition(true); }, 10); }); this.component.pageChange.subscribe(async (event) => { if (this.debug.enabled) console.log("pageChange: event: ", event, ", dims: ", this.getDimensions(this.viewer)); // console.log("pageChange: pages: ", this.getCurrentPagesInView()) setTimeout(() => { // console.log("pageChange: pages: ", this.getCurrentPagesInView()) this.updateViewerPosition(true); }, 10); }); // this.component.zoomChange.subscribe(async (event: any) => { // console.log("zoomChange: event: ", event); // }); this.component.currentZoomFactor.subscribe(async (event) => { if (this.debug.enabled) console.log("currentZoomFactor: event: ", event); // this.updateViewerPosition(); }); if (!this.isMobile()) { // let onWheel = this._zone.runOutsideAngular(() => { // Panning support on desktop document.addEventListener('mousedown', this.boundOnViewerMouseDown); document.addEventListener('mousemove', this.boundOnViewerMouseMove, { passive: false }); document.addEventListener('mouseup', this.boundOnViewerMouseUp); window.addEventListener("wheel", this.boundOnViewerWheel, { passive: false }); }); } else { this._zone.runOutsideAngular(() => { document.addEventListener('touchstart', this.boundOnViewerTouchStart); document.addEventListener('touchmove', this.boundOnViewerTouchMove, { passive: false }); document.addEventListener('touchend', this.boundOnViewerTouchEnd); }); } if (this.debug.enabled) { let onKeyup = (event) => { console.log("onKeyup: event.key: " + event.key); let dims = this.getDimensions(this.viewer); const PDFViewerApplication = window.PDFViewerApplication; if (event.key == "q") { this.viewer.style.transform = `none`; this.viewer.style.transformOrigin = `unset`; this.currentScale = 1.0; let dimsAfter = this.getDimensions(this.viewer); console.log("dimsAfter: ", dimsAfter.scaled); console.log("dimsDiff: ", this.getDimDiff(dims, dimsAfter).scaled); } else if (event.key == "w") { let originX = this.debug.x || dims.parent.width / 2; let originY = this.debug.y || dims.parent.height / 2; originX -= dims.elem.left - dims.parent.left; originY -= dims.elem.top - dims.parent.top; this.currentScale = 1.3; console.log("originX/Y: " + originX + " / " + originY + ", scale: " + this.currentScale + "; dims: ", dims); console.log("originX/Y (%): " + this.debug.nf.format(originX / dims.elem.width * 100) + " / " + this.debug.nf.format(originY / dims.elem.height * 100)); this.viewer.style.transform = `scale(${this.currentScale})`; this.viewer.style.transformOrigin = `${originX}px ${originY}px`; let dimsAfter = this.getDimensions(this.viewer); console.log("dimsAfter: ", dimsAfter.elem); console.log("dimsDiff: ", this.getDimDiff(dims, dimsAfter).elem); } else if (event.key == "e") { // this.viewer.style.transform = `none`; // this.viewer.style.transformOrigin = `unset`; let currentScale = PDFViewerApplication.pdfViewer.currentScale; let newScale = currentScale * this.currentScale; console.log("currentScale: " + currentScale + " -> " + newScale + ", cs: " + this.currentScale + ", dims: ", dims); // PDFViewerApplication.pdfViewer._setScale(newScale, true); this.setViewerScale(newScale, { resetTransform: true }); let dimsAfter = this.getDimensions(this.viewer); console.log("dimsAfter: ", dimsAfter.elem); console.log("dimsDiff: ", this.getDimDiff(dims, dimsAfter).elem); // } else if (event.key == "r") { // Rotate } else if (event.key == "s") { let originX = this.debug.x || dims.parent.width / 2; let originY = this.debug.y || dims.parent.height / 2; originX -= dims.elem.left - dims.parent.left; originY -= dims.elem.top - dims.parent.top; // reset pdfViewer.scale let currentScale = PDFViewerApplication.pdfViewer.currentScale; let prevScale = currentScale / this.currentScale; // console.log("currentScale: " + currentScale + " -> " + prevScale + ", originX/Y: " + originX + " / " + originY); console.log("originX/Y: " + originX + " / " + originY + ", scale: " + currentScale + " -> " + prevScale + ", t.cs: " + this.currentScale + "; dims: ", dims); console.log("originX/Y (%): " + (originX / dims.elem.width) + " / " + (originY / dims.elem.height)); // PDFViewerApplication.pdfViewer._setScale(prevScale, true); if (currentScale != prevScale) this.setViewerScale(prevScale); originX = this.debug.x || dims.parent.width / 2; originY = this.debug.y || dims.parent.height / 2; let dimsAfter = this.getDimensions(this.viewer); originX -= dimsAfter.elem.left - dimsAfter.parent.left; originY -= dimsAfter.elem.top - dimsAfter.parent.top; console.log("originX/Y: " + originX + " / " + originY + ", scale: " + currentScale + " -> " + prevScale + ", t.cs: " + this.currentScale + "; dimsAfter: ", dimsAfter); console.log("originX/Y (%): " + (originX / dimsAfter.elem.width) + " / " + (originY / dimsAfter.elem.height)); this.viewer.style.transform = `scale(${this.currentScale})`; this.viewer.style.transformOrigin = `${originX}px ${originY}px`; } else if (event.key == "t") { // bare PDF.js-zoom let originX = this.debug.x || dims.parent.width / 2; let originY = this.debug.y || dims.parent.height / 2; originX -= dims.elem.left - dims.parent.left; originY -= dims.elem.top - dims.parent.top; if (this.currentScale == 1.0) this.currentScale = 1.3; let currentScale = PDFViewerApplication.pdfViewer.currentScale; let newScale = currentScale * this.currentScale; this.setViewerScale(newScale, { origin: { x: originX, y: originY } }); } else if (event.key == "y") { let originX = this.debug.x || dims.parent.width / 2; let originY = this.debug.y || dims.parent.height / 2; originX -= dims.elem.left - dims.parent.left; originY -= dims.elem.top - dims.parent.top; let currentScale = PDFViewerApplication.pdfViewer.currentScale; let prevScale = currentScale / this.currentScale; console.log("y, currentScale: " + currentScale + "; prevScale: " + prevScale); // PDFViewerApplication.pdfViewer._setScale(prevScale, true); this.setViewerScale(prevScale, { origin: { x: originX, y: originY } }); // this.currentScale = 1.0; // let dimsAfter = this.getDimensions(this.viewer); // console.log("dimsAfter: ", dimsAfter.elem); // console.log("dimsDiff: ", this.getDimDiff(dims, dimsAfter).elem); } else if (event.key == "u") { this.updateViewerPosition(); } else if (event.key == "i") { let corrLeft = 200; console.log("beforeCorr: ", this.getDimensions(this.viewer).elem); console.log("this.viewer.style: ", this.viewer.style); console.log("this.viewer.style.left: " + this.viewer.style.left + " -> " + corrLeft); this.viewer.style.left = corrLeft + "px"; console.log("afterCorr: ", this.getDimensions(this.viewer).elem); console.log("this.viewer.style: ", this.viewer.style); } else if (event.key == "o") { let originX = this.debug.x || dims.parent.width / 2; let originY = this.debug.y || dims.parent.height / 2; originX -= dims.elem.left - dims.parent.left; originY -= dims.elem.top - dims.parent.top; console.log("originX/Y: " + originX + " / " + originY + ", scale: " + this.currentScale); this.viewer.style.transform = `scale(${this.currentScale})`; this.viewer.style.transformOrigin = `${originX}px ${originY}px`; } else if (event.key == "p") { console.log("dims: ", dims); // let originX = this.debug.x || dims.parent.width / 2; // let originY = this.debug.y || dims.parent.height / 2; console.log("getViewerTransformScale: ", this.getViewerTransformScale("key == p")); this.viewer.style.transform = `none`; this.viewer.style.transformOrigin = `unset`; let dimsAfter = this.getDimensions(this.viewer); console.log("dimsAfter: ", dimsAfter); console.log("dimsDiff: ", this.getDimDiff(dims, dimsAfter)); } else if (event.key == "f") { } else if (event.key == "d") { console.log("dims: ", this.getDimensions(this.viewer)); } else if (event.key == "z") { } else if (event.key == "x") { } }; window.addEventListener