UNPKG

ionicx-wechat-like-album

Version:
149 lines (112 loc) 4.7 kB
import { Directive, ElementRef, HostListener } from '@angular/core'; @Directive({ selector: '[pinch-zoom]' }) export class PinchZoomDirective { elem: any; eventType: any; scale: any = 1; initialScale: any = 1; startX: any; startY: any; moveX: any = 0; moveY: any = 0; initialMoveX: any = 0; initialMoveY: any = 0; moveXC: any; moveYC: any; distance: any; initialDistance: any; constructor(private elementRef: ElementRef) { this.elem = this.elementRef.nativeElement; } @HostListener('touchstart', ['$event']) touchstartHandler(event: any) { this.elem.style.transformOrigin = '0 0'; } @HostListener('touchmove', ['$event']) touchmoveHandler(event: any) { try { let touches = event.touches; // Swipe if (touches.length === 1 && this.scale > 1 && !this.eventType || this.eventType == 'swipe') { event.preventDefault(); if (!this.eventType) { this.startX = event.touches[0].pageX; this.startY = event.touches[0].pageY; } this.eventType = 'swipe'; this.moveX = this.initialMoveX + (event.touches[0].pageX - this.startX); this.moveY = this.initialMoveY + (event.touches[0].pageY - this.startY); this.transformElem(0); } // Pinch if (touches.length === 2 && !this.eventType || this.eventType == 'pinch') { event.preventDefault(); if (!this.eventType) { this.initialDistance = this.getDistance(touches); this.moveXC = ((event.touches[0].pageX + event.touches[1].pageX) / 2) - this.initialMoveX; this.moveYC = ((event.touches[0].pageY + event.touches[1].pageY) / 2) - this.initialMoveY; } this.eventType = 'pinch'; this.distance = this.getDistance(touches); this.scale = this.initialScale * (this.distance / this.initialDistance); this.moveX = this.initialMoveX - (((this.distance / this.initialDistance) * this.moveXC) - this.moveXC); this.moveY = this.initialMoveY - (((this.distance / this.initialDistance) * this.moveYC) - this.moveYC); this.transformElem(0); } } catch (e) { } } @HostListener('touchend', ['$event']) touchendHandler(event: any) { let touches = event.touches; let img = this.elem.getElementsByTagName("img")[0]; if (this.scale < 1) { this.scale = 1; } if (this.moveY > 0) { this.moveY = 0; } if (img && this.scale > 1) { let imgHeight = this.getElemHeight(); let imgOffsetTop = ((imgHeight - this.elem.offsetHeight) * this.scale) / 2; if (imgHeight * this.scale < window.innerHeight) { this.moveY = (window.innerHeight - this.elem.offsetHeight * this.scale) / 2; } else if (this.eventType == 'swipe') { if (this.moveY > imgOffsetTop) { this.moveY = imgOffsetTop; } else if ((imgHeight * this.scale + Math.abs(imgOffsetTop) - window.innerHeight) + this.moveY < 0) { this.moveY = - (imgHeight * this.scale + Math.abs(imgOffsetTop) - window.innerHeight); } } } if (this.moveX > 0) { this.moveX = 0; } else if (this.moveX < this.elem.offsetWidth * (1 - this.scale)) { this.moveX = this.elem.offsetWidth * (1 - this.scale); } this.initialScale = this.scale; this.initialMoveX = this.moveX; this.initialMoveY = this.moveY; this.transformElem(200); this.eventType = 'touchend'; if (touches.length == 0) { this.eventType = ''; } } getDistance(touches: any) { return Math.sqrt(Math.pow(touches[0].pageX - touches[1].pageX, 2) + Math.pow(touches[0].pageY - touches[1].pageY, 2)); } getElemHeight() { if (this.elem.getElementsByTagName("img")[0]) { return this.elem.getElementsByTagName("img")[0].offsetHeight; } else { return this.elem.offsetHeight; } } transformElem(duration: any = 50) { this.elem.style.transition = 'all ' + duration + 'ms'; this.elem.style.transform = 'matrix(' + Number(this.scale) + ',' + 0 + ',' + 0 + ',' + Number(this.scale) + ',' + Number(this.moveX) + ',' + Number(this.moveY) + ')'; } }