Skip to content

Instantly share code, notes, and snippets.

@philly-vanilly
Created April 18, 2020 12:07
Show Gist options
  • Save philly-vanilly/1f3b900d4bc23d9a2e8cb91d3ed8abf1 to your computer and use it in GitHub Desktop.
Save philly-vanilly/1f3b900d4bc23d9a2e8cb91d3ed8abf1 to your computer and use it in GitHub Desktop.
import {AfterViewInit, ChangeDetectorRef, Component, ViewChild} from '@angular/core';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import {PdfViewerComponent} from 'ng2-pdf-viewer';
function getMidpoint(x1, y1, x2, y2) {
const x = (x1 + x2) / 2;
const y = (y1 + y2) / 2;
return [x, y];
}
function getDistance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
@Component({
selector: 'app-root',
template: `
<h1 style="background-color: white">PDF.Js Zoom</h1>
<pdf-viewer
[src]="pdfSrc"
[zoom]="pdfZoom"
[render-text]="true"
[original-size]="false"
[show-all]="true"
style="display: block; height: 100%"
></pdf-viewer>
`,
styleUrls: ['app.component.scss']
})
export class AppComponent implements AfterViewInit {
@ViewChild(PdfViewerComponent, {static: false}) private pdfComponent: PdfViewerComponent;
pdfSrc = 'https://vadimdez.github.io/ng2-pdf-viewer/assets/pdf-test.pdf';
pdfZoom = 1;
private pinchZoomEnabled = false;
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private cdr: ChangeDetectorRef
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
ngAfterViewInit(): void {
if (/iphone|ipad|ipod|android|blackberry|bb10|mini|windows\sce|palm/i.test(navigator.userAgent)) {
const metaEl = document.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'width=device-width, initial-scale=1, user-scalable=no');
document.getElementsByTagName('head')[0].appendChild(metaEl);
}
if (!this.pinchZoomEnabled) {
this.pinchZoomEnabled = true;
this.enablePinchZoom(
this.pdfComponent.pdfViewer,
this.pdfComponent.pdfViewerContainer.nativeElement,
this.pdfComponent.pdfViewerContainer.nativeElement.children[0]
);
}
}
private enablePinchZoom(pdfViewer, container: HTMLDivElement, viewer: HTMLDivElement) {
const MAX_PINCH_SCALE_VALUE = 3;
const MAX_SCALE = 10.0;
const MIN_PINCH_SCALE_DELTA = 0.01;
const MIN_PINCH_SCALE_VALUE = 0.25;
const MIN_SCALE = 0.1;
let scaledXOffset;
let scaledYOffset;
let originalXOffset;
let originalYOffset;
let originalDistance = 0;
let pinchScale = 1;
document.addEventListener('touchstart', (event: any) => {
if (event.touches.length > 1) {
const touchMidpoint =
event.pageX && event.pageY
? [event.pageX, event.pageY]
: getMidpoint(
event.touches[0].pageX,
event.touches[0].pageY,
event.touches[1].pageX,
event.touches[1].pageY,
);
// Set the scale point based on the pinch midpoint and scroll offsets
// this.scaledXOffset = this.docEl.scrollLeft - this.pinchPage.offsetLeft + touchMidpoint[0];
// this.scaledYOffset = this.docEl.scrollTop - this.pinchPage.offsetTop + touchMidpoint[1] + 15;
scaledXOffset = container.scrollLeft - viewer.offsetLeft + touchMidpoint[0];
scaledYOffset = container.scrollTop - viewer.offsetTop + touchMidpoint[1] + 15;
viewer.style['transform-origin'] = `${scaledXOffset}px ${scaledYOffset}px`;
// Preserve the original touch offset
originalXOffset = touchMidpoint[0];
originalYOffset = touchMidpoint[1];
// Used by non-iOS browsers that do not provide a scale value
originalDistance = getDistance(
event.touches[0].pageX,
event.touches[0].pageY,
event.touches[1].pageX,
event.touches[1].pageY,
);
} else {
originalDistance = 0;
}
});
document.addEventListener('touchmove', (event: any) => {
if (originalDistance <= 0 || event.touches.length < 2) { return; }
// scale non-standard (missing where?) property exposing distance between two fingers/touches
if ((event as any).scale !== 1) { event.preventDefault(); } // Prevent native iOS page zoom
const scale = event.scale
? event.scale
: getDistance(
event.touches[0].pageX,
event.touches[0].pageY,
event.touches[1].pageX,
event.touches[1].pageY,
) / originalDistance;
// const proposedNewScale = this.pdfViewer.currentScale * scale;
const proposedNewScale = this.pdfZoom * scale;
if (
scale === 1 ||
Math.abs(pinchScale - scale) < MIN_PINCH_SCALE_DELTA ||
proposedNewScale >= MAX_SCALE ||
proposedNewScale <= MIN_SCALE ||
scale > MAX_PINCH_SCALE_VALUE ||
scale < MIN_PINCH_SCALE_VALUE
) {
return;
}
pinchScale = scale;
// this.pinchPage.classList.add(PINCH_PAGE_CLASS);
// this.docEl.firstChild.classList.add(PINCHING_CLASS);
//
viewer.style.transform = `scale(${pinchScale})`;
}, { passive: false });
document.addEventListener('touchend', (e) => {
if (originalDistance <= 0) { return; }
// PDF.js zoom
// this.pdfViewer.currentScaleValue = this.pdfViewer.currentScale * this.pinchScale;
this.pdfZoom = this.pdfZoom * pinchScale;
viewer.style.transform = null;
viewer.style['transform-origin'] = null;
// this.pinchPage.classList.remove(PINCH_PAGE_CLASS);
// this.docEl.firstChild.classList.remove(PINCHING_CLASS);
// Scroll to correct position after zoom
container.scroll(
scaledXOffset * pinchScale - originalXOffset,
scaledYOffset * pinchScale - originalYOffset + viewer.offsetTop,
);
originalDistance = 0;
pinchScale = 1;
});
}
}
@adam-abdulaev
Copy link

Hi. Does this solution work for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment