Source: js/plugins/Animate.js

js/plugins/Animate.js

import { Point } from '@pixi/math';
import { Plugin } from './Plugin';
import ease from '../ease';
const DEFAULT_ANIMATE_OPTIONS = {
    removeOnInterrupt: false,
    ease: 'linear',
    time: 1000,
};
/**
 * Animation plugin.
 *
 * @see Viewport#animate
 * @fires animate-end
 */
export class Animate extends Plugin {
    /**
     * This is called by {@link Viewport.animate}.
     *
     * @param parent
     * @param options
     */
    constructor(parent, options = {}) {
        super(parent);
        /** The starting viewport width. */
        this.startWidth = null;
        /** The starting viewport height. */
        this.startHeight = null;
        /** The change in the viewport's width through the animation. */
        this.deltaWidth = null;
        /** The change in the viewport's height through the animation. */
        this.deltaHeight = null;
        /** The viewport's width post-animation. */
        this.width = null;
        /** The viewport's height post-animation. */
        this.height = null;
        /** The time since the animation started. */
        this.time = 0;
        this.options = Object.assign({}, DEFAULT_ANIMATE_OPTIONS, options);
        this.options.ease = ease(this.options.ease);
        this.setupPosition();
        this.setupZoom();
        this.time = 0;
    }
    /**
     * Setup `startX`, `startY`, `deltaX`, `deltaY`, `keepCenter`.
     *
     * This is called during construction.
     */
    setupPosition() {
        if (typeof this.options.position !== 'undefined') {
            this.startX = this.parent.center.x;
            this.startY = this.parent.center.y;
            this.deltaX = this.options.position.x - this.parent.center.x;
            this.deltaY = this.options.position.y - this.parent.center.y;
            this.keepCenter = false;
        }
        else {
            this.keepCenter = true;
        }
    }
    /**
     * Setup `startWidth, `startHeight`, `deltaWidth, `deltaHeight, `width`, `height`.
     *
     * This is called during construction.
     */
    setupZoom() {
        this.width = null;
        this.height = null;
        if (typeof this.options.scale !== 'undefined') {
            this.width = this.parent.screenWidth / this.options.scale;
        }
        else if (typeof this.options.scaleX !== 'undefined' || typeof this.options.scaleY !== 'undefined') {
            if (typeof this.options.scaleX !== 'undefined') {
                // screenSizeInWorldPixels = screenWidth / scale
                this.width = this.parent.screenWidth / this.options.scaleX;
            }
            if (typeof this.options.scaleY !== 'undefined') {
                this.height = this.parent.screenHeight / this.options.scaleY;
            }
        }
        else {
            if (typeof this.options.width !== 'undefined') {
                this.width = this.options.width;
            }
            if (typeof this.options.height !== 'undefined') {
                this.height = this.options.height;
            }
        }
        if (this.width !== null) {
            this.startWidth = this.parent.screenWidthInWorldPixels;
            this.deltaWidth = this.width - this.startWidth;
        }
        if (this.height !== null) {
            this.startHeight = this.parent.screenHeightInWorldPixels;
            this.deltaHeight = this.height - this.startHeight;
        }
    }
    down() {
        if (this.options.removeOnInterrupt) {
            this.parent.plugins.remove('animate');
        }
        return false;
    }
    complete() {
        this.parent.plugins.remove('animate');
        if (this.width !== null) {
            this.parent.fitWidth(this.width, this.keepCenter, this.height === null);
        }
        if (this.height !== null) {
            this.parent.fitHeight(this.height, this.keepCenter, this.width === null);
        }
        if (!this.keepCenter && this.options.position) {
            this.parent.moveCenter(this.options.position);
        }
        this.parent.emit('animate-end', this.parent);
        if (this.options.callbackOnComplete) {
            this.options.callbackOnComplete(this.parent);
        }
    }
    update(elapsed) {
        if (this.paused) {
            return;
        }
        this.time += elapsed;
        const originalZoom = new Point(this.parent.scale.x, this.parent.scale.y);
        if (this.time >= this.options.time) {
            const originalWidth = this.parent.width;
            const originalHeight = this.parent.height;
            this.complete();
            if (originalWidth !== this.parent.width || originalHeight !== this.parent.height) {
                this.parent.emit('zoomed', { viewport: this.parent, original: originalZoom, type: 'animate' });
            }
        }
        else {
            const percent = this.options.ease(this.time, 0, 1, this.options.time);
            if (this.width !== null) {
                const startWidth = this.startWidth;
                const deltaWidth = this.deltaWidth;
                this.parent.fitWidth(startWidth + (deltaWidth * percent), this.keepCenter, this.height === null);
            }
            if (this.height !== null) {
                const startHeight = this.startHeight;
                const deltaHeight = this.deltaHeight;
                this.parent.fitHeight(startHeight + (deltaHeight * percent), this.keepCenter, this.width === null);
            }
            if (this.width === null) {
                this.parent.scale.x = this.parent.scale.y;
            }
            else if (this.height === null) {
                this.parent.scale.y = this.parent.scale.x;
            }
            if (!this.keepCenter) {
                const startX = this.startX;
                const startY = this.startY;
                const deltaX = this.deltaX;
                const deltaY = this.deltaY;
                const original = new Point(this.parent.x, this.parent.y);
                this.parent.moveCenter(startX + (deltaX * percent), startY + (deltaY * percent));
                this.parent.emit('moved', { viewport: this.parent, original, type: 'animate' });
            }
            if (this.width || this.height) {
                this.parent.emit('zoomed', { viewport: this.parent, original: originalZoom, type: 'animate' });
            }
        }
    }
}