Source: js/plugins/Pinch.js

js/plugins/Pinch.js

import { Plugin } from './Plugin';
const DEFAULT_PINCH_OPTIONS = {
    noDrag: false,
    percent: 1,
    center: null,
    factor: 1,
    axis: 'all',
};
/**
 * Plugin for enabling two-finger pinching (or dragging).
 *
 * @public
 */
export class Pinch extends Plugin {
    /**
     * This is called by {@link Viewport.pinch}.
     */
    constructor(parent, options = {}) {
        super(parent);
        /** Flags whether this plugin is active, i.e. a pointer is down on the viewport. */
        this.active = false;
        /** Flags whether the viewport is being pinched. */
        this.pinching = false;
        this.moved = false;
        this.options = Object.assign({}, DEFAULT_PINCH_OPTIONS, options);
    }
    down() {
        if (this.parent.input.count() >= 2) {
            this.active = true;
            return true;
        }
        return false;
    }
    isAxisX() {
        return ['all', 'x'].includes(this.options.axis);
    }
    isAxisY() {
        return ['all', 'y'].includes(this.options.axis);
    }
    move(e) {
        if (this.paused || !this.active) {
            return false;
        }
        const x = e.data.global.x;
        const y = e.data.global.y;
        const pointers = this.parent.input.touches;
        if (pointers.length >= 2) {
            const first = pointers[0];
            const second = pointers[1];
            const last = (first.last && second.last)
                ? Math.sqrt(Math.pow(second.last.x - first.last.x, 2) + Math.pow(second.last.y - first.last.y, 2))
                : null;
            if (first.id === e.data.pointerId) {
                first.last = { x, y, data: e.data };
            }
            else if (second.id === e.data.pointerId) {
                second.last = { x, y, data: e.data };
            }
            if (last) {
                let oldPoint;
                const point = {
                    x: first.last.x
                        + ((second.last.x - first.last.x) / 2),
                    y: first.last.y
                        + ((second.last.y - first.last.y) / 2),
                };
                if (!this.options.center) {
                    oldPoint = this.parent.toLocal(point);
                }
                let dist = Math.sqrt(Math.pow(second.last.x - first.last.x, 2)
                    + Math.pow(second.last.y - first.last.y, 2));
                dist = dist === 0 ? dist = 0.0000000001 : dist;
                const change = (1 - (last / dist)) * this.options.percent
                    * (this.isAxisX() ? this.parent.scale.x : this.parent.scale.y);
                if (this.isAxisX()) {
                    this.parent.scale.x += change;
                }
                if (this.isAxisY()) {
                    this.parent.scale.y += change;
                }
                this.parent.emit('zoomed', { viewport: this.parent, type: 'pinch', center: point });
                const clamp = this.parent.plugins.get('clamp-zoom', true);
                if (clamp) {
                    clamp.clamp();
                }
                if (this.options.center) {
                    this.parent.moveCenter(this.options.center);
                }
                else {
                    const newPoint = this.parent.toGlobal(oldPoint);
                    this.parent.x += (point.x - newPoint.x) * this.options.factor;
                    this.parent.y += (point.y - newPoint.y) * this.options.factor;
                    this.parent.emit('moved', { viewport: this.parent, type: 'pinch' });
                }
                if (!this.options.noDrag && this.lastCenter) {
                    this.parent.x += (point.x - this.lastCenter.x) * this.options.factor;
                    this.parent.y += (point.y - this.lastCenter.y) * this.options.factor;
                    this.parent.emit('moved', { viewport: this.parent, type: 'pinch' });
                }
                this.lastCenter = point;
                this.moved = true;
            }
            else if (!this.pinching) {
                this.parent.emit('pinch-start', this.parent);
                this.pinching = true;
            }
            return true;
        }
        return false;
    }
    up() {
        if (this.pinching) {
            if (this.parent.input.touches.length <= 1) {
                this.active = false;
                this.lastCenter = null;
                this.pinching = false;
                this.moved = false;
                this.parent.emit('pinch-end', this.parent);
                return true;
            }
        }
        return false;
    }
}