ionicx-wechat-like-album
Version:
a album is like the wechat for ionic
149 lines (112 loc) • 4.7 kB
text/typescript
import { Directive, ElementRef, HostListener } from '@angular/core';
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;
}
touchstartHandler(event: any) {
this.elem.style.transformOrigin = '0 0';
}
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) {
}
}
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) + ')';
}
}