pixi-game-camera
Version:
A flexible and non-opinionated way to add camera effects to your PIXI application via containers.
102 lines (85 loc) • 3.1 kB
text/typescript
'use strict'
import { Container } from '@pixi/display';
import { Effect } from './effect';
import { Vector } from '../vector';
/**
* A panning effect that makes the camera focus on a point in the container.
*/
export class PanTo extends Effect {
/**
* The (x, y) coordinate pair to pan to.
*
* @private
*
* @property {Vector}
*/
private _coordinates: Vector;
/**
* The difference in coordinates from the current and the desired.
*
* @private
*
* @property {Vector}
*/
private _difference: Vector;
/**
* Indicates whether the desired x is greater than the current x or not.
*
* @private
*
* @property {boolean}
*
* @default false
*/
private _xIsGreater = false;
/**
* Indicates whether the desired y is greater than the current y or not.
*
* @private
*
* @property {boolean}
*
* @default false
*/
private _yIsGreater = false;
/**
* @param {Container} container A reference to the container to apply the panto effect to.
* @param {number} x The x coordinate to pan to.
* @param {number} y The y coordinate to pan to.
* @param {number} duration The amount of time, in milliseconds, that the effect should take.
*/
constructor(container: Container, x: number, y: number, duration: number) {
super(container);
this._coordinates = { x, y };
this.duration = duration;
if (this._coordinates.x > this.container.pivot.x) this._xIsGreater = true;
if (this._coordinates.y > this.container.pivot.y) this._yIsGreater = true;
this._difference = { x: Math.abs(this._coordinates.x - this.container.pivot.x), y: Math.abs(this._coordinates.y - this.container.pivot.y) };
}
/**
* Updates the status of this effect on a frame by frame basis.
*/
update() {
if (this.criteriaMet()) {
this.finished.dispatch();
return;
}
this.current = performance.now();
const timeDiffPercentage = (this.current - this.started) / this.duration;
const timeDiffPercentageNegative = (this.duration - this.current) / this.duration;
const xPanAmount = this._xIsGreater ? this._difference.x * timeDiffPercentage : this._difference.x * timeDiffPercentageNegative;
const yPanAmount = this._yIsGreater ? this._difference.y * timeDiffPercentage : this._difference.y * timeDiffPercentageNegative;
this.container.pivot.x = xPanAmount;
this.container.pivot.y = yPanAmount;
if (this.useRAF) this.id = requestAnimationFrame(() => this.update());
}
/**
* Checks to see if the panto criteria has been met so that the effect can end.
*
* @returns {boolean} Returns true if the panto effect is finished or false otherwise.
*/
criteriaMet(): boolean {
if (this.container.pivot.x > this._coordinates.x - 5 && this.container.pivot.x < this._coordinates.x + 5 && this.container.pivot.y > this._coordinates.y - 5 && this.container.pivot.y < this._coordinates.y + 5) return true;
return false;
}
}