Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pinch zoom #397

Open
lemartva opened this Issue Dec 5, 2017 · 4 comments

Comments

Projects
None yet
4 participants
@lemartva
Copy link

lemartva commented Dec 5, 2017

Do you have any plan to implement pinch zoom?
Thanks for a great plugin.

@ngt14

This comment has been minimized.

Copy link

ngt14 commented Dec 19, 2017

Hello @lemartva, you can use Hammer.JS to get pinch zoom event.
[https://hammerjs.github.io/]

@lemartva

This comment has been minimized.

Copy link
Author

lemartva commented Dec 22, 2017

Awesome @ngt14 ! I'm going to check hammerjs, Thanks.

@yehudahkay

This comment has been minimized.

Copy link

yehudahkay commented May 15, 2018

+1

@Bengejd

This comment has been minimized.

Copy link

Bengejd commented Jul 19, 2018

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);
    });
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.