Source: js/plugins/SnapZoom.js

js/plugins/SnapZoom.js

import { Plugin } from './Plugin';
import ease from '../ease';
const DEFAULT_SNAP_ZOOM_OPTIONS = {
    width: 0,
    height: 0,
    time: 1000,
    ease: 'easeInOutSine',
    center: null,
    interrupt: true,
    removeOnComplete: false,
    removeOnInterrupt: false,
    forceStart: false,
    noMove: false
};
/**
 * @event snap-zoom-start(Viewport) emitted each time a fit animation starts
 * @event snap-zoom-end(Viewport) emitted each time fit reaches its target
 * @event snap-zoom-end(Viewport) emitted each time fit reaches its target
 */
export class SnapZoom extends Plugin {
    /**
     * This is called by {@link Viewport.snapZoom}.
     */
    constructor(parent, options = {}) {
        super(parent);
        this.options = Object.assign({}, DEFAULT_SNAP_ZOOM_OPTIONS, options);
        this.ease = ease(this.options.ease);
        // Assign defaults for typescript.
        this.xIndependent = false;
        this.yIndependent = false;
        this.xScale = 0;
        this.yScale = 0;
        if (this.options.width > 0) {
            this.xScale = parent.screenWidth / this.options.width;
            this.xIndependent = true;
        }
        if (this.options.height > 0) {
            this.yScale = parent.screenHeight / this.options.height;
            this.yIndependent = true;
        }
        this.xScale = this.xIndependent ? this.xScale : this.yScale;
        this.yScale = this.yIndependent ? this.yScale : this.xScale;
        if (this.options.time === 0) {
            // TODO: Fix this
            // @ts-expect-error todo
            parent.container.scale.x = this.xScale;
            // TODO: Fix this
            // @ts-expect-error todo
            parent.container.scale.y = this.yScale;
            if (this.options.removeOnComplete) {
                this.parent.plugins.remove('snap-zoom');
            }
        }
        else if (options.forceStart) {
            this.createSnapping();
        }
    }
    createSnapping() {
        const startWorldScreenWidth = this.parent.worldScreenWidth;
        const startWorldScreenHeight = this.parent.worldScreenHeight;
        const endWorldScreenWidth = this.parent.screenWidth / this.xScale;
        const endWorldScreenHeight = this.parent.screenHeight / this.yScale;
        this.snapping = {
            time: 0,
            startX: startWorldScreenWidth,
            startY: startWorldScreenHeight,
            deltaX: endWorldScreenWidth - startWorldScreenWidth,
            deltaY: endWorldScreenHeight - startWorldScreenHeight
        };
        this.parent.emit('snap-zoom-start', this.parent);
    }
    resize() {
        this.snapping = null;
        if (this.options.width > 0) {
            this.xScale = this.parent.screenWidth / this.options.width;
        }
        if (this.options.height > 0) {
            this.yScale = this.parent.screenHeight / this.options.height;
        }
        this.xScale = this.xIndependent ? this.xScale : this.yScale;
        this.yScale = this.yIndependent ? this.yScale : this.xScale;
    }
    wheel() {
        if (this.options.removeOnInterrupt) {
            this.parent.plugins.remove('snap-zoom');
        }
        return false;
    }
    down() {
        if (this.options.removeOnInterrupt) {
            this.parent.plugins.remove('snap-zoom');
        }
        else if (this.options.interrupt) {
            this.snapping = null;
        }
        return false;
    }
    update(elapsed) {
        if (this.paused) {
            return;
        }
        if (this.options.interrupt && this.parent.input.count() !== 0) {
            return;
        }
        let oldCenter;
        if (!this.options.center && !this.options.noMove) {
            oldCenter = this.parent.center;
        }
        if (!this.snapping) {
            if (this.parent.scale.x !== this.xScale || this.parent.scale.y !== this.yScale) {
                this.createSnapping();
            }
        }
        else if (this.snapping) {
            const snapping = this.snapping;
            snapping.time += elapsed;
            if (snapping.time >= this.options.time) {
                this.parent.scale.set(this.xScale, this.yScale);
                if (this.options.removeOnComplete) {
                    this.parent.plugins.remove('snap-zoom');
                }
                this.parent.emit('snap-zoom-end', this.parent);
                this.snapping = null;
            }
            else {
                const snapping = this.snapping;
                const worldScreenWidth = this.ease(snapping.time, snapping.startX, snapping.deltaX, this.options.time);
                const worldScreenHeight = this.ease(snapping.time, snapping.startY, snapping.deltaY, this.options.time);
                this.parent.scale.x = this.parent.screenWidth / worldScreenWidth;
                this.parent.scale.y = this.parent.screenHeight / worldScreenHeight;
            }
            const clamp = this.parent.plugins.get('clamp-zoom', true);
            if (clamp) {
                clamp.clamp();
            }
            if (!this.options.noMove) {
                if (!this.options.center) {
                    this.parent.moveCenter(oldCenter);
                }
                else {
                    this.parent.moveCenter(this.options.center);
                }
            }
        }
    }
    resume() {
        this.snapping = null;
        super.resume();
    }
}