type fixes: (#48)
- assigned proper types for all the 'any' - changed let to const in all the appropriate places - removed unused code and variables - add 'private' access for all the internal stuff
This commit is contained in:
parent
4651b629cb
commit
65528874b3
6 changed files with 294 additions and 252 deletions
|
|
@ -1,5 +1,5 @@
|
|||
export interface Properties {
|
||||
element?: string;
|
||||
element?: HTMLElement;
|
||||
doubleTap?: boolean;
|
||||
doubleTapScale?: number;
|
||||
zoomControlScale?: number;
|
||||
|
|
@ -10,8 +10,7 @@ export interface Properties {
|
|||
limitPan?: boolean;
|
||||
minPanScale?: number;
|
||||
minScale?: number;
|
||||
eventHandler?: any;
|
||||
listeners?: string | 'auto' | 'mouse and touch';
|
||||
listeners?: 'auto' | 'mouse and touch';
|
||||
wheel?: boolean;
|
||||
fullImage?: {
|
||||
path: string;
|
||||
|
|
|
|||
|
|
@ -1,55 +1,49 @@
|
|||
import { Touches } from './touches';
|
||||
import { EventType, Touches } from './touches';
|
||||
import { Properties } from './interfaces';
|
||||
import { defaultProperties } from './properties';
|
||||
|
||||
type PropertyName = keyof Properties;
|
||||
|
||||
export class IvyPinch {
|
||||
properties: Properties = defaultProperties;
|
||||
touches: any;
|
||||
element: any;
|
||||
elementTarget: any;
|
||||
parentElement: any;
|
||||
i: number = 0;
|
||||
private readonly properties: Properties = defaultProperties;
|
||||
private touches: Touches;
|
||||
private readonly element: HTMLElement;
|
||||
private readonly elementTarget: string;
|
||||
private parentElement: HTMLElement;
|
||||
public scale: number = 1;
|
||||
initialScale: number = 1;
|
||||
elementPosition: any;
|
||||
eventType: any;
|
||||
startX: number = 0;
|
||||
startY: number = 0;
|
||||
moveX: number = 0;
|
||||
moveY: number = 0;
|
||||
initialMoveX: number = 0;
|
||||
initialMoveY: number = 0;
|
||||
moveXC: number = 0;
|
||||
moveYC: number = 0;
|
||||
lastTap: number = 0;
|
||||
draggingMode: boolean = false;
|
||||
distance: number = 0;
|
||||
doubleTapTimeout: number = 0;
|
||||
initialDistance: number = 0;
|
||||
events: any = {};
|
||||
maxScale!: number;
|
||||
defaultMaxScale: number = 3;
|
||||
private initialScale: number = 1;
|
||||
private elementPosition: DOMRect;
|
||||
private eventType: EventType;
|
||||
private startX: number = 0;
|
||||
private startY: number = 0;
|
||||
private moveX: number = 0;
|
||||
private moveY: number = 0;
|
||||
private initialMoveX: number = 0;
|
||||
private initialMoveY: number = 0;
|
||||
private moveXC: number = 0;
|
||||
private moveYC: number = 0;
|
||||
private distance: number = 0;
|
||||
private initialDistance: number = 0;
|
||||
public maxScale!: number;
|
||||
private defaultMaxScale: number = 3;
|
||||
|
||||
// Minimum scale at which panning works
|
||||
get minPanScale() {
|
||||
get minPanScale(): number {
|
||||
return this.getPropertiesValue('minPanScale');
|
||||
}
|
||||
|
||||
get fullImage() {
|
||||
get fullImage(): { path: string; minScale?: number } {
|
||||
return this.properties.fullImage;
|
||||
}
|
||||
|
||||
constructor(properties: any) {
|
||||
constructor(properties: Properties) {
|
||||
this.element = properties.element;
|
||||
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof properties.limitZoom === 'number')
|
||||
if (typeof properties.limitZoom === 'number') {
|
||||
this.maxScale = properties.limitZoom;
|
||||
}
|
||||
this.elementTarget = this.element.querySelector('*').tagName;
|
||||
this.parentElement = this.element.parentElement;
|
||||
this.properties = Object.assign({}, defaultProperties, properties);
|
||||
|
|
@ -96,8 +90,8 @@ export class IvyPinch {
|
|||
|
||||
/* Touchstart */
|
||||
|
||||
handleTouchstart = (event: any) => {
|
||||
this.touches.addEventListeners('mousemove', 'handleMousemove');
|
||||
private handleTouchstart = (event: TouchEvent | MouseEvent): void => {
|
||||
this.touches.addEventListeners('mousemove');
|
||||
this.getElementPosition();
|
||||
|
||||
if (this.eventType === undefined) {
|
||||
|
|
@ -107,12 +101,10 @@ export class IvyPinch {
|
|||
|
||||
/* Touchend */
|
||||
|
||||
handleTouchend = (event: any) => {
|
||||
private handleTouchend = (event: TouchEvent | MouseEvent): void => {
|
||||
/* touchend */
|
||||
if (event.type === 'touchend') {
|
||||
this.i = 0;
|
||||
this.draggingMode = false;
|
||||
const touches = event.touches;
|
||||
const touches = (event as TouchEvent).touches;
|
||||
|
||||
// Min scale
|
||||
if (this.scale < 1) {
|
||||
|
|
@ -148,19 +140,18 @@ export class IvyPinch {
|
|||
|
||||
/* mouseup */
|
||||
if (event.type === 'mouseup') {
|
||||
this.draggingMode = false;
|
||||
this.updateInitialValues();
|
||||
this.eventType = undefined;
|
||||
}
|
||||
|
||||
this.touches.removeEventListeners('mousemove', 'handleMousemove');
|
||||
this.touches.removeEventListeners('mousemove');
|
||||
};
|
||||
|
||||
/*
|
||||
* Handlers
|
||||
*/
|
||||
|
||||
handlePan = (event: any) => {
|
||||
private handlePan = (event: TouchEvent | MouseEvent): void => {
|
||||
if (this.scale < this.minPanScale || this.properties.disablePan) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -190,12 +181,12 @@ export class IvyPinch {
|
|||
this.transformElement(0);
|
||||
};
|
||||
|
||||
handleDoubleTap = (event: any) => {
|
||||
private handleDoubleTap = (event: TouchEvent): void => {
|
||||
this.toggleZoom(event);
|
||||
return;
|
||||
};
|
||||
|
||||
handlePinch = (event: any) => {
|
||||
private handlePinch = (event: TouchEvent): void => {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.eventType === undefined || this.eventType === 'pinch') {
|
||||
|
|
@ -230,11 +221,11 @@ export class IvyPinch {
|
|||
}
|
||||
};
|
||||
|
||||
handleWheel = (event: any) => {
|
||||
private handleWheel = (event: WheelEvent): void => {
|
||||
event.preventDefault();
|
||||
|
||||
let wheelZoomFactor = this.properties.wheelZoomFactor || 0;
|
||||
let zoomFactor = event.deltaY < 0 ? wheelZoomFactor : -wheelZoomFactor;
|
||||
const wheelZoomFactor = this.properties.wheelZoomFactor || 0;
|
||||
const zoomFactor = event.deltaY < 0 ? wheelZoomFactor : -wheelZoomFactor;
|
||||
let newScale = this.initialScale + zoomFactor;
|
||||
|
||||
/* Round value */
|
||||
|
|
@ -256,8 +247,8 @@ export class IvyPinch {
|
|||
this.scale = newScale;
|
||||
|
||||
/* Get cursor position over image */
|
||||
let xCenter = event.clientX - this.elementPosition.left - this.initialMoveX;
|
||||
let yCenter = event.clientY - this.elementPosition.top - this.initialMoveY;
|
||||
const xCenter = event.clientX - this.elementPosition.left - this.initialMoveX;
|
||||
const yCenter = event.clientY - this.elementPosition.top - this.initialMoveY;
|
||||
|
||||
this.setZoom({
|
||||
scale: newScale,
|
||||
|
|
@ -265,11 +256,11 @@ export class IvyPinch {
|
|||
});
|
||||
};
|
||||
|
||||
handleResize = (_event: any) => {
|
||||
private handleResize = (_event: Event): void => {
|
||||
this.setAutoHeight();
|
||||
};
|
||||
|
||||
handleLimitZoom() {
|
||||
private handleLimitZoom(): void {
|
||||
const limitZoom = this.maxScale;
|
||||
const minScale = this.properties.minScale || 0;
|
||||
|
||||
|
|
@ -297,12 +288,12 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
moveLeft(event: any, index: number = 0) {
|
||||
private moveLeft(event: TouchEvent | MouseEvent, index: number = 0): number {
|
||||
const clientX = this.getClientPosition(event, index).clientX;
|
||||
return clientX - this.elementPosition.left;
|
||||
}
|
||||
|
||||
moveTop(event: any, index: number = 0) {
|
||||
private moveTop(event: TouchEvent | MouseEvent, index: number = 0): number {
|
||||
const clientY = this.getClientPosition(event, index).clientY;
|
||||
return clientY - this.elementPosition.top;
|
||||
}
|
||||
|
|
@ -311,8 +302,8 @@ export class IvyPinch {
|
|||
* Detection
|
||||
*/
|
||||
|
||||
centeringImage() {
|
||||
const img = this.element.getElementsByTagName(this.elementTarget)[0];
|
||||
private centeringImage(): boolean {
|
||||
const img = this.getImageElement();
|
||||
const initialMoveX = this.moveX;
|
||||
const initialMoveY = this.moveY;
|
||||
|
||||
|
|
@ -336,7 +327,7 @@ export class IvyPinch {
|
|||
return initialMoveX !== this.moveX || initialMoveY !== this.moveY;
|
||||
}
|
||||
|
||||
limitPanY() {
|
||||
private limitPanY(): void {
|
||||
const imgHeight = this.getImageHeight();
|
||||
const scaledImgHeight = imgHeight * this.scale;
|
||||
const parentHeight = this.parentElement.offsetHeight;
|
||||
|
|
@ -355,7 +346,7 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
limitPanX() {
|
||||
private limitPanX(): void {
|
||||
const imgWidth = this.getImageWidth();
|
||||
const scaledImgWidth = imgWidth * this.scale;
|
||||
const parentWidth = this.parentElement.offsetWidth;
|
||||
|
|
@ -374,7 +365,7 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
setBasicStyles() {
|
||||
private setBasicStyles(): void {
|
||||
this.element.style.display = 'flex';
|
||||
this.element.style.alignItems = 'center';
|
||||
this.element.style.justifyContent = 'center';
|
||||
|
|
@ -383,7 +374,7 @@ export class IvyPinch {
|
|||
this.setDraggableImage();
|
||||
}
|
||||
|
||||
removeBasicStyles() {
|
||||
private removeBasicStyles(): void {
|
||||
this.element.style.display = '';
|
||||
this.element.style.alignItems = '';
|
||||
this.element.style.justifyContent = '';
|
||||
|
|
@ -392,7 +383,7 @@ export class IvyPinch {
|
|||
this.removeDraggableImage();
|
||||
}
|
||||
|
||||
setDraggableImage() {
|
||||
private setDraggableImage(): void {
|
||||
const imgElement = this.getImageElement();
|
||||
|
||||
if (imgElement) {
|
||||
|
|
@ -400,7 +391,7 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
removeDraggableImage() {
|
||||
private removeDraggableImage(): void {
|
||||
const imgElement = this.getImageElement();
|
||||
|
||||
if (imgElement) {
|
||||
|
|
@ -408,8 +399,8 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
setImageSize() {
|
||||
const imgElement = this.element.getElementsByTagName(this.elementTarget);
|
||||
private setImageSize(): void {
|
||||
const imgElement = this.getImageElements();
|
||||
|
||||
if (imgElement.length) {
|
||||
imgElement[0].style.maxWidth = '100%';
|
||||
|
|
@ -419,8 +410,8 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
setAutoHeight() {
|
||||
const imgElement = this.element.getElementsByTagName(this.elementTarget);
|
||||
private setAutoHeight(): void {
|
||||
const imgElement = this.getImageElements();
|
||||
|
||||
if (!this.properties.autoHeight || !imgElement.length) {
|
||||
return;
|
||||
|
|
@ -428,14 +419,14 @@ export class IvyPinch {
|
|||
|
||||
const imgNaturalWidth = imgElement[0].getAttribute('width');
|
||||
const imgNaturalHeight = imgElement[0].getAttribute('height');
|
||||
const sizeRatio = imgNaturalWidth / imgNaturalHeight;
|
||||
const sizeRatio = +imgNaturalWidth / +imgNaturalHeight;
|
||||
const parentWidth = this.parentElement.offsetWidth;
|
||||
|
||||
imgElement[0].style.maxHeight = parentWidth / sizeRatio + 'px';
|
||||
}
|
||||
|
||||
removeImageSize() {
|
||||
const imgElement = this.element.getElementsByTagName(this.elementTarget);
|
||||
private removeImageSize(): void {
|
||||
const imgElement = this.getImageElements();
|
||||
|
||||
if (imgElement.length) {
|
||||
imgElement[0].style.maxWidth = '';
|
||||
|
|
@ -443,28 +434,28 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
getElementPosition() {
|
||||
private getElementPosition(): void {
|
||||
this.elementPosition = this.element.parentElement.getBoundingClientRect();
|
||||
}
|
||||
|
||||
getTouchstartPosition(event: any) {
|
||||
private getTouchstartPosition(event: TouchEvent | MouseEvent): void {
|
||||
const { clientX, clientY } = this.getClientPosition(event);
|
||||
|
||||
this.startX = clientX - this.elementPosition.left;
|
||||
this.startY = clientY - this.elementPosition.top;
|
||||
}
|
||||
|
||||
getClientPosition(event: any, index: number = 0) {
|
||||
let clientX;
|
||||
let clientY;
|
||||
private getClientPosition(event: TouchEvent | MouseEvent, index: number = 0): { clientX: number; clientY: number } {
|
||||
let clientX: number;
|
||||
let clientY: number;
|
||||
|
||||
if (event.type === 'touchstart' || event.type === 'touchmove') {
|
||||
clientX = event.touches[index].clientX;
|
||||
clientY = event.touches[index].clientY;
|
||||
clientX = (event as TouchEvent).touches[index].clientX;
|
||||
clientY = (event as TouchEvent).touches[index].clientY;
|
||||
}
|
||||
if (event.type === 'mousedown' || event.type === 'mousemove') {
|
||||
clientX = event.clientX;
|
||||
clientY = event.clientY;
|
||||
clientX = (event as MouseEvent).clientX;
|
||||
clientY = (event as MouseEvent).clientY;
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -473,7 +464,7 @@ export class IvyPinch {
|
|||
};
|
||||
}
|
||||
|
||||
resetScale() {
|
||||
private resetScale(): void {
|
||||
this.scale = 1;
|
||||
this.moveX = 0;
|
||||
this.moveY = 0;
|
||||
|
|
@ -481,33 +472,43 @@ export class IvyPinch {
|
|||
this.transformElement(this.properties.transitionDuration);
|
||||
}
|
||||
|
||||
updateInitialValues() {
|
||||
private updateInitialValues(): void {
|
||||
this.initialScale = this.scale;
|
||||
this.initialMoveX = this.moveX;
|
||||
this.initialMoveY = this.moveY;
|
||||
}
|
||||
|
||||
getDistance(touches: any) {
|
||||
return Math.sqrt(Math.pow(touches[0].pageX - touches[1].pageX, 2) + Math.pow(touches[0].pageY - touches[1].pageY, 2));
|
||||
private getDistance(touches: TouchList): number {
|
||||
return Math.sqrt(
|
||||
Math.pow(touches[0].pageX - touches[1].pageX, 2) + Math.pow(touches[0].pageY - touches[1].pageY, 2),
|
||||
);
|
||||
}
|
||||
|
||||
getImageHeight() {
|
||||
const img = this.element.getElementsByTagName(this.elementTarget)[0];
|
||||
private getImageHeight(): number {
|
||||
const img = this.getImageElement() as HTMLImageElement;
|
||||
return img.offsetHeight;
|
||||
}
|
||||
|
||||
getImageWidth() {
|
||||
const img = this.element.getElementsByTagName(this.elementTarget)[0];
|
||||
private getImageWidth(): number {
|
||||
const img = this.getImageElement() as HTMLImageElement;
|
||||
return img.offsetWidth;
|
||||
}
|
||||
|
||||
transformElement(duration: any) {
|
||||
private transformElement(duration: number): void {
|
||||
this.element.style.transition = 'all ' + duration + 'ms';
|
||||
this.element.style.transform =
|
||||
'matrix(' + Number(this.scale) + ', 0, 0, ' + Number(this.scale) + ', ' + Number(this.moveX) + ', ' + Number(this.moveY) + ')';
|
||||
'matrix(' +
|
||||
Number(this.scale) +
|
||||
', 0, 0, ' +
|
||||
Number(this.scale) +
|
||||
', ' +
|
||||
Number(this.moveX) +
|
||||
', ' +
|
||||
Number(this.moveY) +
|
||||
')';
|
||||
}
|
||||
|
||||
isTouchScreen() {
|
||||
private isTouchScreen(): boolean {
|
||||
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
|
||||
if ('ontouchstart' in window) {
|
||||
|
|
@ -520,11 +521,11 @@ export class IvyPinch {
|
|||
return this.getMatchMedia(query);
|
||||
}
|
||||
|
||||
getMatchMedia(query: any) {
|
||||
private getMatchMedia(query: string): boolean {
|
||||
return window.matchMedia(query).matches;
|
||||
}
|
||||
|
||||
isDragging() {
|
||||
public isDragging(): boolean {
|
||||
if (this.properties.disablePan) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -533,7 +534,10 @@ export class IvyPinch {
|
|||
const imgWidth = this.getImageWidth();
|
||||
|
||||
if (this.scale > 1) {
|
||||
return imgHeight * this.scale > this.parentElement.offsetHeight || imgWidth * this.scale > this.parentElement.offsetWidth;
|
||||
return (
|
||||
imgHeight * this.scale > this.parentElement.offsetHeight ||
|
||||
imgWidth * this.scale > this.parentElement.offsetWidth
|
||||
);
|
||||
}
|
||||
if (this.scale === 1) {
|
||||
return imgHeight > this.parentElement.offsetHeight || imgWidth > this.parentElement.offsetWidth;
|
||||
|
|
@ -542,7 +546,7 @@ export class IvyPinch {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
detectLimitZoom() {
|
||||
public detectLimitZoom(): void {
|
||||
// Assign to default only if it is not passed through constructor
|
||||
this.maxScale ??= this.defaultMaxScale;
|
||||
|
||||
|
|
@ -552,9 +556,9 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
pollLimitZoomForOriginalImage() {
|
||||
let poll = setInterval(() => {
|
||||
let maxScaleForOriginalImage = this.getMaxScaleForOriginalImage();
|
||||
private pollLimitZoomForOriginalImage(): void {
|
||||
const poll = setInterval(() => {
|
||||
const maxScaleForOriginalImage = this.getMaxScaleForOriginalImage();
|
||||
if (typeof maxScaleForOriginalImage === 'number') {
|
||||
this.maxScale = maxScaleForOriginalImage;
|
||||
clearInterval(poll);
|
||||
|
|
@ -562,9 +566,9 @@ export class IvyPinch {
|
|||
}, 10);
|
||||
}
|
||||
|
||||
getMaxScaleForOriginalImage() {
|
||||
private getMaxScaleForOriginalImage(): number {
|
||||
let maxScale!: number;
|
||||
let img = this.element.getElementsByTagName('img')[0];
|
||||
const img = this.element.getElementsByTagName('img')[0];
|
||||
|
||||
if (img.naturalWidth && img.offsetWidth) {
|
||||
maxScale = img.naturalWidth / img.offsetWidth;
|
||||
|
|
@ -573,29 +577,35 @@ export class IvyPinch {
|
|||
return maxScale;
|
||||
}
|
||||
|
||||
getImageElement() {
|
||||
private getImageElement(): HTMLElement {
|
||||
const imgElement = this.element.getElementsByTagName(this.elementTarget);
|
||||
|
||||
if (imgElement.length) {
|
||||
return imgElement[0];
|
||||
return imgElement[0] as HTMLElement;
|
||||
}
|
||||
}
|
||||
|
||||
toggleZoom(event: any = false) {
|
||||
private getImageElements(): HTMLCollectionOf<HTMLElement> {
|
||||
return this.element.getElementsByTagName(this.elementTarget) as HTMLCollectionOf<HTMLElement>;
|
||||
}
|
||||
|
||||
public toggleZoom(event: TouchEvent | boolean = false): void {
|
||||
if (this.initialScale === 1) {
|
||||
if (event && event.changedTouches) {
|
||||
if (event && (event as TouchEvent).changedTouches) {
|
||||
if (this.properties.doubleTapScale === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const changedTouches = event.changedTouches;
|
||||
const changedTouches = (event as TouchEvent).changedTouches;
|
||||
this.scale = this.initialScale * this.properties.doubleTapScale;
|
||||
this.moveX =
|
||||
this.initialMoveX - (changedTouches[0].clientX - this.elementPosition.left) * (this.properties.doubleTapScale - 1);
|
||||
this.initialMoveX -
|
||||
(changedTouches[0].clientX - this.elementPosition.left) * (this.properties.doubleTapScale - 1);
|
||||
this.moveY =
|
||||
this.initialMoveY - (changedTouches[0].clientY - this.elementPosition.top) * (this.properties.doubleTapScale - 1);
|
||||
this.initialMoveY -
|
||||
(changedTouches[0].clientY - this.elementPosition.top) * (this.properties.doubleTapScale - 1);
|
||||
} else {
|
||||
let zoomControlScale = this.properties.zoomControlScale || 0;
|
||||
const zoomControlScale = this.properties.zoomControlScale || 0;
|
||||
this.scale = this.initialScale * (zoomControlScale + 1);
|
||||
this.moveX = this.initialMoveX - (this.element.offsetWidth * (this.scale - 1)) / 2;
|
||||
this.moveY = this.initialMoveY - (this.element.offsetHeight * (this.scale - 1)) / 2;
|
||||
|
|
@ -609,14 +619,14 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
setZoom(properties: { scale: number; center?: number[] }) {
|
||||
private setZoom(properties: { scale: number; center?: number[] }): void {
|
||||
this.scale = properties.scale;
|
||||
|
||||
let xCenter;
|
||||
let yCenter;
|
||||
let visibleAreaWidth = this.element.offsetWidth;
|
||||
let visibleAreaHeight = this.element.offsetHeight;
|
||||
let scalingPercent = (visibleAreaWidth * this.scale) / (visibleAreaWidth * this.initialScale);
|
||||
const visibleAreaWidth = this.element.offsetWidth;
|
||||
const visibleAreaHeight = this.element.offsetHeight;
|
||||
const scalingPercent = (visibleAreaWidth * this.scale) / (visibleAreaWidth * this.initialScale);
|
||||
|
||||
if (properties.center) {
|
||||
xCenter = properties.center[0];
|
||||
|
|
@ -634,7 +644,7 @@ export class IvyPinch {
|
|||
this.transformElement(this.properties.transitionDuration);
|
||||
}
|
||||
|
||||
alignImage() {
|
||||
private alignImage(): void {
|
||||
const isMoveChanged = this.centeringImage();
|
||||
|
||||
if (isMoveChanged) {
|
||||
|
|
@ -643,12 +653,12 @@ export class IvyPinch {
|
|||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
public destroy(): void {
|
||||
this.removeBasicStyles();
|
||||
this.touches.destroy();
|
||||
}
|
||||
|
||||
getPropertiesValue(propertyName: PropertyName) {
|
||||
private getPropertiesValue<K extends keyof Properties>(propertyName: K): Properties[K] {
|
||||
if (this.properties && this.properties[propertyName]) {
|
||||
return this.properties[propertyName];
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
<div class="pinch-zoom-content" [class.pz-dragging]="isDragging">
|
||||
<ng-content></ng-content>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
<!-- Control: one button -->
|
||||
<div
|
||||
@if (isControl()) {
|
||||
<div
|
||||
class="pz-zoom-button pz-zoom-control-position-bottom"
|
||||
[class.pz-zoom-button-out]="isZoomedIn"
|
||||
*ngIf="isControl()"
|
||||
(click)="toggleZoom()"
|
||||
></div>
|
||||
></div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ChangeDetectorRef, Component, ElementRef, HostBinding, HostListener, Input, OnDestroy, SimpleChanges } from '@angular/core';
|
||||
import { Component, ElementRef, HostBinding, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
|
||||
import { Properties } from './interfaces';
|
||||
import { defaultProperties, backwardCompatibilityProperties } from './properties';
|
||||
|
|
@ -17,24 +17,21 @@ export const _defaultComponentProperties: ComponentProperties = {
|
|||
backgroundColor: 'rgba(0,0,0,0.85)',
|
||||
};
|
||||
|
||||
type PropertyName = keyof ComponentProperties;
|
||||
|
||||
@Component({
|
||||
selector: 'pinch-zoom, [pinch-zoom]',
|
||||
exportAs: 'pinchZoom',
|
||||
templateUrl: './pinch-zoom.component.html',
|
||||
styleUrls: ['./pinch-zoom.component.sass'],
|
||||
})
|
||||
export class PinchZoomComponent implements OnDestroy {
|
||||
pinchZoom: any;
|
||||
_properties!: ComponentProperties;
|
||||
defaultComponentProperties!: ComponentProperties;
|
||||
zoomControlPositionClass: string | undefined;
|
||||
_transitionDuration!: number;
|
||||
_doubleTap!: boolean;
|
||||
_doubleTapScale!: number;
|
||||
_autoZoomOut!: boolean;
|
||||
_limitZoom!: number | 'original image size';
|
||||
export class PinchZoomComponent implements OnInit, OnDestroy, OnChanges {
|
||||
private pinchZoom: IvyPinch;
|
||||
private _properties!: ComponentProperties;
|
||||
private readonly defaultComponentProperties!: ComponentProperties;
|
||||
private _transitionDuration!: number;
|
||||
private _doubleTap!: boolean;
|
||||
private _doubleTapScale!: number;
|
||||
private _autoZoomOut!: boolean;
|
||||
private _limitZoom!: number | 'original image size';
|
||||
|
||||
@Input('properties') set properties(value: ComponentProperties) {
|
||||
if (value) {
|
||||
|
|
@ -42,7 +39,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get properties() {
|
||||
get properties(): ComponentProperties {
|
||||
return this._properties;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +56,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get transitionDuration() {
|
||||
get transitionDuration(): number {
|
||||
return this._transitionDuration;
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +73,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get doubleTap() {
|
||||
get doubleTap(): boolean {
|
||||
return this._doubleTap;
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +90,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get doubleTapScale() {
|
||||
get doubleTapScale(): number {
|
||||
return this._doubleTapScale;
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +107,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get autoZoomOut() {
|
||||
get autoZoomOut(): boolean {
|
||||
return this._autoZoomOut;
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +124,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get limitZoom() {
|
||||
get limitZoom(): number | 'original image size' {
|
||||
return this._limitZoom;
|
||||
}
|
||||
|
||||
|
|
@ -147,18 +144,18 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
@Input() draggableImage!: boolean;
|
||||
|
||||
@HostBinding('style.overflow')
|
||||
get hostOverflow() {
|
||||
get hostOverflow(): 'hidden' | 'visible' {
|
||||
return this.properties['overflow'];
|
||||
}
|
||||
|
||||
@HostBinding('style.background-color')
|
||||
get hostBackgroundColor() {
|
||||
get hostBackgroundColor(): string {
|
||||
return this.properties['backgroundColor'];
|
||||
}
|
||||
|
||||
get isTouchScreen() {
|
||||
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
var mq = function (query: any) {
|
||||
get isTouchScreen(): boolean {
|
||||
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
const mq = (query: string): boolean => {
|
||||
return window.matchMedia(query).matches;
|
||||
};
|
||||
|
||||
|
|
@ -168,79 +165,81 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
get isDragging() {
|
||||
return this.pinchZoom ? this.pinchZoom.isDragging() : undefined;
|
||||
get isDragging(): boolean {
|
||||
return this.pinchZoom?.isDragging();
|
||||
}
|
||||
|
||||
get isDisabled() {
|
||||
return this.properties['disabled'];
|
||||
get isDisabled(): boolean {
|
||||
return this._properties.disabled;
|
||||
}
|
||||
|
||||
get scale() {
|
||||
get scale(): number {
|
||||
return this.pinchZoom.scale;
|
||||
}
|
||||
|
||||
get isZoomedIn() {
|
||||
get isZoomedIn(): boolean {
|
||||
return this.scale > 1;
|
||||
}
|
||||
|
||||
get scaleLevel() {
|
||||
get scaleLevel(): number {
|
||||
return Math.round(this.scale / this._zoomControlScale);
|
||||
}
|
||||
|
||||
get maxScale() {
|
||||
get maxScale(): number {
|
||||
return this.pinchZoom.maxScale;
|
||||
}
|
||||
|
||||
get isZoomLimitReached() {
|
||||
get isZoomLimitReached(): boolean {
|
||||
return this.scale >= this.maxScale;
|
||||
}
|
||||
|
||||
get _zoomControlScale() {
|
||||
get _zoomControlScale(): number {
|
||||
return this.getPropertiesValue('zoomControlScale');
|
||||
}
|
||||
|
||||
constructor(private elementRef: ElementRef) {
|
||||
constructor(private elementRef: ElementRef<HTMLElement>) {
|
||||
this.defaultComponentProperties = this.getDefaultComponentProperties();
|
||||
this.applyPropertiesDefault(this.defaultComponentProperties, {});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit(): void {
|
||||
this.initPinchZoom();
|
||||
|
||||
/* Calls the method until the image size is available */
|
||||
this.detectLimitZoom();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
let changedProperties = this.getProperties(changes);
|
||||
changedProperties = this.renameProperties(changedProperties);
|
||||
|
||||
this.applyPropertiesDefault(this.defaultComponentProperties, changedProperties);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
ngOnDestroy(): void {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
initPinchZoom() {
|
||||
if (this.properties['disabled']) {
|
||||
private initPinchZoom(): void {
|
||||
if (this._properties.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.properties.limitZoom = this.limitZoom;
|
||||
this.properties['element'] = this.elementRef.nativeElement.querySelector('.pinch-zoom-content');
|
||||
this._properties.limitZoom = this.limitZoom;
|
||||
this._properties.element = this.elementRef.nativeElement.querySelector('.pinch-zoom-content');
|
||||
this.pinchZoom = new IvyPinch(this.properties);
|
||||
}
|
||||
|
||||
getProperties(changes: SimpleChanges) {
|
||||
let properties: any = {};
|
||||
private getProperties(
|
||||
changes: SimpleChanges,
|
||||
): ComponentProperties | Record<keyof typeof backwardCompatibilityProperties, unknown> {
|
||||
let properties: ComponentProperties = {};
|
||||
|
||||
for (var prop in changes) {
|
||||
for (const prop in changes) {
|
||||
if (prop !== 'properties') {
|
||||
properties[prop] = changes[prop].currentValue;
|
||||
}
|
||||
|
|
@ -251,52 +250,52 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
return properties;
|
||||
}
|
||||
|
||||
renameProperties(properties: any) {
|
||||
for (var prop in properties) {
|
||||
private renameProperties(
|
||||
properties: ComponentProperties | Record<keyof typeof backwardCompatibilityProperties, unknown>,
|
||||
): ComponentProperties {
|
||||
for (const prop in properties) {
|
||||
if (backwardCompatibilityProperties[prop]) {
|
||||
properties[backwardCompatibilityProperties[prop]] = properties[prop];
|
||||
delete properties[prop];
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
return properties as ComponentProperties;
|
||||
}
|
||||
|
||||
applyPropertiesDefault(defaultProperties: ComponentProperties, properties: ComponentProperties): void {
|
||||
private applyPropertiesDefault(defaultProperties: ComponentProperties, properties: ComponentProperties): void {
|
||||
this.properties = Object.assign({}, defaultProperties, properties);
|
||||
}
|
||||
|
||||
toggleZoom() {
|
||||
this.pinchZoom.toggleZoom();
|
||||
toggleZoom(): void {
|
||||
this.pinchZoom?.toggleZoom();
|
||||
}
|
||||
|
||||
isControl() {
|
||||
isControl(): boolean {
|
||||
if (this.isDisabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.properties['disableZoomControl'] === 'disable') {
|
||||
if (this._properties.disableZoomControl === 'disable') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isTouchScreen && this.properties['disableZoomControl'] === 'auto') {
|
||||
if (this.isTouchScreen && this._properties.disableZoomControl === 'auto') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
detectLimitZoom() {
|
||||
if (this.pinchZoom) {
|
||||
this.pinchZoom.detectLimitZoom();
|
||||
}
|
||||
detectLimitZoom(): void {
|
||||
this.pinchZoom?.detectLimitZoom();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.pinchZoom) this.pinchZoom.destroy();
|
||||
destroy(): void {
|
||||
this.pinchZoom?.destroy();
|
||||
}
|
||||
|
||||
getPropertiesValue(propertyName: PropertyName) {
|
||||
private getPropertiesValue<K extends keyof ComponentProperties>(propertyName: K): ComponentProperties[K] {
|
||||
if (this.properties && this.properties[propertyName]) {
|
||||
return this.properties[propertyName];
|
||||
} else {
|
||||
|
|
@ -304,7 +303,7 @@ export class PinchZoomComponent implements OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
getDefaultComponentProperties() {
|
||||
private getDefaultComponentProperties(): ComponentProperties {
|
||||
return { ...defaultProperties, ..._defaultComponentProperties };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export const defaultProperties: Properties = {
|
|||
draggableImage: false,
|
||||
};
|
||||
|
||||
export const backwardCompatibilityProperties: any = {
|
||||
export const backwardCompatibilityProperties = {
|
||||
'transition-duration': 'transitionDuration',
|
||||
transitionDurationBackwardCompatibility: 'transitionDuration',
|
||||
'double-tap': 'doubleTap',
|
||||
|
|
|
|||
|
|
@ -1,56 +1,77 @@
|
|||
export interface Properties {
|
||||
element: HTMLElement;
|
||||
listeners?: 'auto' | 'mouse and touch';
|
||||
touchListeners?: any;
|
||||
mouseListeners?: any;
|
||||
otherListeners?: any;
|
||||
touchListeners?: TouchListeners;
|
||||
mouseListeners?: MouseListeners;
|
||||
otherListeners?: OtherListeners;
|
||||
resize?: boolean;
|
||||
}
|
||||
|
||||
export type EventType = undefined | 'touchend' | 'pan' | 'pinch' | 'horizontal-swipe' | 'vertical-swipe' | 'tap' | 'longtap';
|
||||
export type TouchHandler = 'handleTouchstart' | 'handleTouchmove' | 'handleTouchend';
|
||||
export type MouseHandler = 'handleMousedown' | 'handleMousemove' | 'handleMouseup';
|
||||
export type EventType =
|
||||
| undefined
|
||||
| 'touchstart'
|
||||
| 'touchend'
|
||||
| 'touchmove'
|
||||
| 'mousedown'
|
||||
| 'mouseup'
|
||||
| 'mousemove'
|
||||
| 'pan'
|
||||
| 'pinch'
|
||||
| 'horizontal-swipe'
|
||||
| 'vertical-swipe'
|
||||
| 'tap'
|
||||
| 'longtap'
|
||||
| 'wheel'
|
||||
| 'double-tap'
|
||||
| 'resize';
|
||||
export type TouchHandler ='handleTouchstart' | 'handleTouchmove' | 'handleTouchend';
|
||||
export type MouseHandler = 'handleMousedown' | 'handleMousemove' | 'handleMouseup' | 'handleWheel';
|
||||
export type OtherHandler = 'handleResize';
|
||||
|
||||
export type TouchListeners = Partial<Record<'touchstart' | 'touchmove' | 'touchend', TouchHandler>>;
|
||||
export type MouseListeners = Partial<Record<'mousedown' | 'mousemove' | 'mouseup' | 'wheel', MouseHandler>>;
|
||||
export type OtherListeners = Partial<Record<'resize', OtherHandler>>;
|
||||
|
||||
export class Touches {
|
||||
properties: Properties;
|
||||
element: HTMLElement;
|
||||
elementPosition: ClientRect;
|
||||
eventType: EventType = undefined;
|
||||
handlers: any = {};
|
||||
startX = 0;
|
||||
startY = 0;
|
||||
lastTap = 0;
|
||||
doubleTapTimeout: any;
|
||||
doubleTapMinTimeout = 300;
|
||||
tapMinTimeout = 200;
|
||||
touchstartTime = 0;
|
||||
i: number = 0;
|
||||
isMousedown = false;
|
||||
private properties: Properties;
|
||||
private element: HTMLElement;
|
||||
private elementPosition: DOMRect;
|
||||
private eventType: EventType = undefined;
|
||||
private handlers: TouchListeners | MouseListeners | OtherListeners = {};
|
||||
private startX = 0;
|
||||
private startY = 0;
|
||||
private lastTap = 0;
|
||||
private doubleTapTimeout: number;
|
||||
private doubleTapMinTimeout = 300;
|
||||
private tapMinTimeout = 200;
|
||||
private touchstartTime = 0;
|
||||
private i: number = 0;
|
||||
private isMousedown = false;
|
||||
|
||||
_touchListeners: any = {
|
||||
private _touchListeners: Record<'touchstart' | 'touchmove' | 'touchend', TouchHandler> = {
|
||||
touchstart: 'handleTouchstart',
|
||||
touchmove: 'handleTouchmove',
|
||||
touchend: 'handleTouchend',
|
||||
};
|
||||
_mouseListeners: any = {
|
||||
private _mouseListeners: Record<'mousedown' | 'mousemove' | 'mouseup' | 'wheel', MouseHandler> = {
|
||||
mousedown: 'handleMousedown',
|
||||
mousemove: 'handleMousemove',
|
||||
mouseup: 'handleMouseup',
|
||||
wheel: 'handleWheel',
|
||||
};
|
||||
_otherListeners: any = {
|
||||
private _otherListeners: Record<'resize', OtherHandler> = {
|
||||
resize: 'handleResize',
|
||||
};
|
||||
|
||||
get touchListeners() {
|
||||
private get touchListeners(): TouchListeners {
|
||||
return this.properties.touchListeners ? this.properties.touchListeners : this._touchListeners;
|
||||
}
|
||||
|
||||
get mouseListeners() {
|
||||
private get mouseListeners(): MouseListeners {
|
||||
return this.properties.mouseListeners ? this.properties.mouseListeners : this._mouseListeners;
|
||||
}
|
||||
|
||||
get otherListeners() {
|
||||
private get otherListeners(): OtherListeners {
|
||||
return this.properties.otherListeners ? this.properties.otherListeners : this._otherListeners;
|
||||
}
|
||||
|
||||
|
|
@ -62,12 +83,12 @@ export class Touches {
|
|||
this.toggleEventListeners('addEventListener');
|
||||
}
|
||||
|
||||
destroy() {
|
||||
public destroy(): void {
|
||||
this.toggleEventListeners('removeEventListener');
|
||||
}
|
||||
|
||||
toggleEventListeners(action: 'addEventListener' | 'removeEventListener') {
|
||||
let listeners;
|
||||
private toggleEventListeners(action: 'addEventListener' | 'removeEventListener'): void {
|
||||
let listeners: TouchListeners | MouseListeners | OtherListeners;
|
||||
|
||||
if (this.properties.listeners === 'mouse and touch') {
|
||||
listeners = Object.assign(this.touchListeners, this.mouseListeners);
|
||||
|
|
@ -79,8 +100,8 @@ export class Touches {
|
|||
listeners = Object.assign(listeners, this.otherListeners);
|
||||
}
|
||||
|
||||
for (var listener in listeners) {
|
||||
const handler: MouseHandler = listeners[listener];
|
||||
for (const listener in listeners) {
|
||||
const handler = listeners[listener];
|
||||
|
||||
// Window
|
||||
if (listener === 'resize') {
|
||||
|
|
@ -110,12 +131,12 @@ export class Touches {
|
|||
}
|
||||
}
|
||||
|
||||
addEventListeners(listener: string) {
|
||||
public addEventListeners(listener: string): void {
|
||||
const handler: MouseHandler = this._mouseListeners[listener];
|
||||
window.addEventListener(listener, this[handler], false);
|
||||
}
|
||||
|
||||
removeEventListeners(listener: string) {
|
||||
public removeEventListeners(listener: string): void {
|
||||
const handler: MouseHandler = this._mouseListeners[listener];
|
||||
window.removeEventListener(listener, this[handler], false);
|
||||
}
|
||||
|
|
@ -126,7 +147,7 @@ export class Touches {
|
|||
|
||||
/* Touchstart */
|
||||
|
||||
handleTouchstart = (event: any) => {
|
||||
private handleTouchstart = (event: TouchEvent): void => {
|
||||
this.elementPosition = this.getElementPosition();
|
||||
this.touchstartTime = new Date().getTime();
|
||||
|
||||
|
|
@ -139,7 +160,7 @@ export class Touches {
|
|||
|
||||
/* Touchmove */
|
||||
|
||||
handleTouchmove = (event: any) => {
|
||||
private handleTouchmove = (event: TouchEvent): void => {
|
||||
const touches = event.touches;
|
||||
|
||||
// Pan
|
||||
|
|
@ -153,7 +174,7 @@ export class Touches {
|
|||
}
|
||||
};
|
||||
|
||||
handleLinearSwipe(event: any) {
|
||||
private handleLinearSwipe(event: any): void {
|
||||
//event.preventDefault();
|
||||
|
||||
this.i++;
|
||||
|
|
@ -173,7 +194,7 @@ export class Touches {
|
|||
|
||||
/* Touchend */
|
||||
|
||||
handleTouchend = (event: any) => {
|
||||
private handleTouchend = (event: TouchEvent): void => {
|
||||
const touches = event.touches;
|
||||
|
||||
// Double Tap
|
||||
|
|
@ -195,7 +216,7 @@ export class Touches {
|
|||
|
||||
/* Mousedown */
|
||||
|
||||
handleMousedown = (event: any) => {
|
||||
private handleMousedown = (event: MouseEvent): void => {
|
||||
this.isMousedown = true;
|
||||
this.elementPosition = this.getElementPosition();
|
||||
this.touchstartTime = new Date().getTime();
|
||||
|
|
@ -209,7 +230,7 @@ export class Touches {
|
|||
|
||||
/* Mousemove */
|
||||
|
||||
handleMousemove = (event: any) => {
|
||||
private handleMousemove = (event: MouseEvent): void => {
|
||||
//event.preventDefault();
|
||||
|
||||
if (!this.isMousedown) {
|
||||
|
|
@ -222,24 +243,32 @@ export class Touches {
|
|||
// Linear swipe
|
||||
switch (this.detectLinearSwipe(event)) {
|
||||
case 'horizontal-swipe':
|
||||
// FIXME: looks like an error
|
||||
// @ts-ignore
|
||||
event.swipeType = 'horizontal-swipe';
|
||||
this.runHandler('horizontal-swipe', event);
|
||||
break;
|
||||
case 'vertical-swipe':
|
||||
// FIXME: looks like an error
|
||||
// @ts-ignore
|
||||
event.swipeType = 'vertical-swipe';
|
||||
this.runHandler('vertical-swipe', event);
|
||||
break;
|
||||
}
|
||||
|
||||
// Linear swipe
|
||||
if (this.detectLinearSwipe(event) || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
|
||||
if (
|
||||
this.detectLinearSwipe(event) ||
|
||||
this.eventType === 'horizontal-swipe' ||
|
||||
this.eventType === 'vertical-swipe'
|
||||
) {
|
||||
this.handleLinearSwipe(event);
|
||||
}
|
||||
};
|
||||
|
||||
/* Mouseup */
|
||||
|
||||
handleMouseup = (event: any) => {
|
||||
private handleMouseup = (event: MouseEvent): void => {
|
||||
// Tap
|
||||
this.detectTap();
|
||||
|
||||
|
|
@ -251,19 +280,19 @@ export class Touches {
|
|||
|
||||
/* Wheel */
|
||||
|
||||
handleWheel = (event: any) => {
|
||||
private handleWheel = (event: WheelEvent): void => {
|
||||
this.runHandler('wheel', event);
|
||||
};
|
||||
|
||||
/* Resize */
|
||||
|
||||
handleResize = (event: any) => {
|
||||
private handleResize = (event: Event): void => {
|
||||
this.runHandler('resize', event);
|
||||
};
|
||||
|
||||
runHandler(eventName: any, response: any) {
|
||||
private runHandler(eventName: EventType, event: unknown):void {
|
||||
if (this.handlers[eventName]) {
|
||||
this.handlers[eventName](response);
|
||||
this.handlers[eventName](event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,11 +300,11 @@ export class Touches {
|
|||
* Detection
|
||||
*/
|
||||
|
||||
detectPan(touches: any) {
|
||||
private detectPan(touches: TouchList): boolean {
|
||||
return (touches.length === 1 && !this.eventType) || this.eventType === 'pan';
|
||||
}
|
||||
|
||||
detectDoubleTap() {
|
||||
private detectDoubleTap(): boolean {
|
||||
if (this.eventType != undefined) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -283,13 +312,13 @@ export class Touches {
|
|||
const currentTime = new Date().getTime();
|
||||
const tapLength = currentTime - this.lastTap;
|
||||
|
||||
clearTimeout(this.doubleTapTimeout);
|
||||
window.clearTimeout(this.doubleTapTimeout);
|
||||
|
||||
if (tapLength < this.doubleTapMinTimeout && tapLength > 0) {
|
||||
return true;
|
||||
} else {
|
||||
this.doubleTapTimeout = setTimeout(() => {
|
||||
clearTimeout(this.doubleTapTimeout);
|
||||
this.doubleTapTimeout = window.setTimeout(() => {
|
||||
window.clearTimeout(this.doubleTapTimeout);
|
||||
}, this.doubleTapMinTimeout);
|
||||
}
|
||||
this.lastTap = currentTime;
|
||||
|
|
@ -297,7 +326,7 @@ export class Touches {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
detectTap(): void {
|
||||
private detectTap(): void {
|
||||
if (this.eventType != undefined) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -314,16 +343,20 @@ export class Touches {
|
|||
}
|
||||
}
|
||||
|
||||
detectPinch(event: any) {
|
||||
private detectPinch(event: TouchEvent): boolean {
|
||||
const touches = event.touches;
|
||||
return (touches.length === 2 && this.eventType === undefined) || this.eventType === 'pinch';
|
||||
}
|
||||
|
||||
detectLinearSwipe(event: any) {
|
||||
const touches = event.touches;
|
||||
private detectLinearSwipe(event: MouseEvent | TouchEvent): 'vertical-swipe' | 'horizontal-swipe' {
|
||||
const touches = (event as TouchEvent).touches;
|
||||
|
||||
if (touches) {
|
||||
if ((touches.length === 1 && !this.eventType) || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
|
||||
if (
|
||||
(touches.length === 1 && !this.eventType) ||
|
||||
this.eventType === 'horizontal-swipe' ||
|
||||
this.eventType === 'vertical-swipe'
|
||||
) {
|
||||
return this.getLinearSwipeType(event);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -335,7 +368,7 @@ export class Touches {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
getLinearSwipeType(event: any) {
|
||||
private getLinearSwipeType(event: TouchEvent | MouseEvent): 'vertical-swipe' | 'horizontal-swipe' {
|
||||
if (this.eventType !== 'horizontal-swipe' && this.eventType !== 'vertical-swipe') {
|
||||
const movementX = Math.abs(this.moveLeft(0, event) - this.startX);
|
||||
const movementY = Math.abs(this.moveTop(0, event) - this.startY);
|
||||
|
|
@ -350,43 +383,43 @@ export class Touches {
|
|||
}
|
||||
}
|
||||
|
||||
getElementPosition() {
|
||||
private getElementPosition(): DOMRect {
|
||||
return this.element.getBoundingClientRect();
|
||||
}
|
||||
|
||||
getTouchstartPosition(event: any) {
|
||||
private getTouchstartPosition(event: TouchEvent): void {
|
||||
this.startX = event.touches[0].clientX - this.elementPosition.left;
|
||||
this.startY = event.touches[0].clientY - this.elementPosition.top;
|
||||
}
|
||||
|
||||
getMousedownPosition(event: any) {
|
||||
private getMousedownPosition(event: MouseEvent): void {
|
||||
this.startX = event.clientX - this.elementPosition.left;
|
||||
this.startY = event.clientY - this.elementPosition.top;
|
||||
}
|
||||
|
||||
moveLeft(index: any, event: any) {
|
||||
const touches = event.touches;
|
||||
private moveLeft(index: number, event: TouchEvent | MouseEvent): number {
|
||||
const touches = (event as TouchEvent).touches;
|
||||
|
||||
if (touches) {
|
||||
return touches[index].clientX - this.elementPosition.left;
|
||||
} else {
|
||||
return event.clientX - this.elementPosition.left;
|
||||
return (event as MouseEvent).clientX - this.elementPosition.left;
|
||||
}
|
||||
}
|
||||
|
||||
moveTop(index: any, event: any) {
|
||||
const touches = event.touches;
|
||||
private moveTop(index: number, event: TouchEvent | MouseEvent): number {
|
||||
const touches = (event as TouchEvent).touches;
|
||||
|
||||
if (touches) {
|
||||
return touches[index].clientY - this.elementPosition.top;
|
||||
} else {
|
||||
return event.clientY - this.elementPosition.top;
|
||||
return (event as MouseEvent).clientY - this.elementPosition.top;
|
||||
}
|
||||
}
|
||||
|
||||
detectTouchScreen() {
|
||||
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
var mq = function (query: any) {
|
||||
private detectTouchScreen(): boolean {
|
||||
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
const mq = (query: string): boolean => {
|
||||
return window.matchMedia(query).matches;
|
||||
};
|
||||
|
||||
|
|
@ -396,12 +429,12 @@ export class Touches {
|
|||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
/* Public properties and methods */
|
||||
on(event: EventType, handler: Function) {
|
||||
public on(event: EventType, handler: (event: Event) => void): void {
|
||||
if (event) {
|
||||
this.handlers[event] = handler;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue