Open lemartva opened 6 years ago
Hello @lemartva, you can use Hammer.JS to get pinch zoom event. [https://hammerjs.github.io/]
Awesome @ngt14 ! I'm going to check hammerjs, Thanks.
+1
Here is how you handle pinch events for zooming.
Import this directive into your module
import { Directive, HostListener, ElementRef, Output, EventEmitter, AfterViewInit, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/distinctUntilChanged';
@Directive({
selector: '[pinch]'
})
export class PinchDirective implements AfterViewInit, OnDestroy {
// flag that is set when 2 fingers touch the screen
private isPinching = false;
// initial scale no need to change
private scale = 1;
// store the initial distance between the fingers
// so we can calculate with it
private initalDistance;
// used to store the Observable created from the touchmove event
// so we can unsubscribe from it when ngDestroy is called
private touchMove;
constructor(
// the actual element
private el: ElementRef
) { }
public ngAfterViewInit() {
// start Observing the touchmove event
this.touchMove = Observable
.fromEvent(this.el.nativeElement, 'touchmove')
// since both fingers trigger a move event, broadcast only
// a new scale what it actually changed
.distinctUntilChanged()
.subscribe((event) => {
// call the onTouchMove
this.onTouchMove(event);
});
}
// extend the outputs to your needs, for now we just use
// the defaults, tag move, start and end
@Output()
public pinchmove: EventEmitter<any> = new EventEmitter();
@Output()
public pinchstart: EventEmitter<any> = new EventEmitter();
@Output()
public pinchend: EventEmitter<any> = new EventEmitter();
@HostListener('touchstart', ['$event'])
public onTouchStart(e) {
// set the flag to true, only if 2 fingers touch te screen
if (e.touches.length === 2) {
// emit the touchStart event
this.pinchstart.emit(e);
this.isPinching = true;
}
}
@HostListener('touchend', ['$event'])
public onTouchEnd(e) {
if (this.isPinching) {
// reset the initial distance
this.initalDistance = undefined;
// we are not scaling anymore
this.isPinching = false;
this.pinchend.emit(e);
}
}
private onTouchMove(e) {
// are we pinching?
if (this.isPinching) {
// calculate the initial distance if not set
if (!this.initalDistance) {
this.initalDistance = this.getDistance(e);
}
// round the scale to 2 decimals, so the distinctUntilChanged
// can do its work properly
// console.log((this.getScale(e) * 100) / 100);
// this.scale = Math.round(this.getScale(e) * 100) / 100;
this.scale = this.getScale(e);
// emit the scale!
this.pinchmove.emit({ scale: this.scale });
}
}
// calculate the scale
private getScale(e) {
return this.getDistance(e) / this.initalDistance;
}
// just some basic math to calculate the distance between two points
private getDistance(e) {
let touch0 = e.touches[0];
let touch1 = e.touches[1];
return Math.sqrt(
(touch0.pageX - touch1.pageX) * (touch0.pageX - touch1.pageX) +
(touch0.pageY - touch1.pageY) * (touch0.pageY - touch1.pageY)
);
}
// clean things up
public ngOnDestroy() {
this.touchMove.unsubscribe();
}
}
Set up your template file to handle the pinch events.
<div pinch
(pinchstart)="onPinchStart($event)"
(pinchend)="onPinchEnd($event)"
(pinchmove)="onPinchMove($event)">
The pinch functions go in your component
onPinchMove(e) {
// set the cameraZoom so we can track it globally
this.cameraZoom = e.scale;
// total amount we cameraZoomd
let totalScaled = this.currentZoom * e.scale;
// did we hit the max cameraZoom (pinch out)
if (totalScaled >= MAX_ZOOM) {
// fix the cameraZoom by calculating it, don't use the e.cameraZoom
// scenario: an insane quick pinch out will offset the this.cameraZoom
this.cameraZoom = MAX_ZOOM / this.currentZoom;
totalScaled = MAX_ZOOM;
console.log('Hit the max zoom!');
return;
// did we hit the min cameraZoom (pinch in)
} else if (totalScaled <= MIN_ZOOM) {
// fix the cameraZoom
this.cameraZoom = MIN_ZOOM / this.currentZoom;
totalScaled = MIN_ZOOM;
console.log('Hit the min zoom!');
return;
}
this.cameraPreview.setZoom(totalScaled);
console.log(totalScaled);
}
onPinchStart(e) {
// flag that sets the class to disable scrolling
this.isZooming = true;
}
onPinchEnd(e) {
// flip the flag, enable scrolling
this.isZooming = false;
// adjust the amount we already cameraZoomd
this.currentZoom = this.cameraZoom * this.currentZoom;
}
Now set the zoom for the camera
setZoom(zoom) {
return this.cameraPreview.setZoom(zoom)
.catch(err => {
log.error('CameraPreviewService: An error occured while setting the camera zoom: ', err);
});
}
Do you have any plan to implement pinch zoom? Thanks for a great plugin.