Source: Sprite.js

/**
 * @class       Sprite
 * @description Base class for position based objects
 * @author      Chris Peters
 *
 * @param {Integer} [x] The initial x position. Default is 0
 * @param {Integer} [y] The initial y position. Default is 0
 */
class Sprite {
    constructor(x = 0, y = 0) {
        this._x = x;
        this._y = y;
        this._pivotX = 1;
        this._pivotY = 1;
        this._width = 0;
        this._height = 0;
        this._scaleX = 1;
        this._scaleY = 1;
        this._rotation = 0;
        /**
         * The composite operation type. Can be source-atop|source-in|source-out|source-over|destination-atop|destination-in|destination-out|destination-over|lighter|xor|copy
         * Default is 'source-over'
         *
         * @member Sprite#_composite
         * @type {String}
         */
        this._composite = Sprite._compositeDefault;
        this._opacity = 1;
    }

    /**
     * @method Sprite.getCompositeDefault
     * @return {String}
     */
    static getCompositeDefault() {
        return Sprite._compositeDefault;
    }

    /**
     * @return {Object} The bounding area
     */
    getBoundingArea() {
        return {
            maxX: this._x + (this._width  * this._scaleX),
            maxY: this._y + (this._height * this._scaleY),
            minX: this._x,
            minY: this._y
        };
    }

    /**
     * @method Sprite#getComposite
     * @return {String}
     */
    getComposite() {
        return this._composite;
    }

    /**
     * @method Sprite#getHeight
     * @return {Integer}
     */
    getHeight() {
        return this._height;
    }

    /**
     * @method Sprite#getOpacity
     * @return {Float}
     */
    getOpacity() {
        return this._opacity;
    }

    /**
     * @method Sprite#getPivotX
     * @return {Integer}
     */
    getPivotX() {
        return this._pivotX;
    }

    /**
     * @method Sprite#getPivotY
     * @return {Integer}
     */
    getPivotY() {
        return this._pivotY;
    }

    /**
     * @method Sprite#getRotation
     * @return {Float}
     */
    getRotation() {
        return this._rotation;
    }

    /**
     * @method Sprite#getRotation
     * @return {Float}
     */
    getRotationRadians() {
        return this._rotation;
    }

    /**
     * @method Sprite#getScaleX
     * @return {Integer}
     */
    getScaleX() {
        return this._scaleX;
    }

    /**
     * @method Sprite#getScaleY
     * @return {Integer}
     */
    getScaleY() {
        return this._scaleY;
    }

    /**
     * @method Sprite#getSrcHeight
     * @return {Integer}
     */
    getSrcHeight() {
        return this._srcHeight;
    }

    /**
     * @method Sprite#getSrcWidth
     * @return {Integer}
     */
    getSrcWidth() {
        return this._srcWidth;
    }

    /**
     * @method Sprite#getSrcX
     * @return {Integer}
     */
    getSrcX() {
        return this._srcX;
    }

    /**
     * @method Sprite#getSrcY
     * @return {Integer}
     */
    getSrcY() {
        return this._srcY;
    }

    /**
     * @method Sprite#getWidth
     * @return {Integer}
     */
    getWidth() {
        return this._width;
    }

    /**
     * @method Sprite#getX
     * @return {Integer}
     */
    getX() {
        return this._x;
    }

    /**
     * @method Sprite#getY
     * @return {Integer}
     */
    getY() {
        return this._y;
    }

    /**
     * @method Sprite#render
     * @param  {Object} context The canvas' context
     */
    render(context, factor, ticks) {
        context.translate(
            this._x + this._pivotX,
            this._y + this._pivotY
        );
        context.scale(this._scaleX, this._scaleY);

        if (this._rotation !== 0) {
            context.translate(-this._pivotX, -this._pivotY);
            context.rotate(this._rotation);
            context.translate(-this._pivotX, -this._pivotY);
        }
    }

    /**
     *
     * @method Sprite#setComposite
     * @param  {Integer} val The composite value
     * @return {Sprite}
     */
    setComposite(val) {
        this._composite = val;

        return this;
    }

    /**
     *
     * @method Sprite#setHeight
     * @param  {Integer} val The height value
     * @return {Sprite}
     */
    setHeight(val) {
        this._height = val;

        return this;
    }

    /**
     *
     * @method Sprite#setOpacity
     * @param  {Float} val The opacity value
     * @return {Sprite}
     */
    setOpacity(val) {
        this._opacity = val;

        return this;
    }

    /**
     * @method Sprite#setPivotX
     * @param  {Float} val The opacity value
     * @return {Sprite}
     */
    setPivotX(val) {
        this._pivotX = val;

        return this;
    }

    /**
     * @method Sprite#setPivotY
     * @param  {Float} val The opacity value
     * @return {Sprite}
     */
    setPivotY(val) {
        this._pivotY = val;

        return this;
    }

    /**
     *
     * @method Sprite#setRotation
     * @param  {Integer} val The rotation value
     * @return {Sprite}
     */
    setRotation(val) {
        this._rotation = val * Math.PI / 180;

        return this;
    }

    /**
     *
     * @method Sprite#setScaleX
     * @param  {Integer} val The scaleX value
     * @return {Sprite}
     */
    setScaleX(val) {
        this._scaleX = val;

        return this;
    }

    /**
     *
     * @method Sprite#setScaleY
     * @param  {Integer} val The scaleY value
     * @return {Sprite}
     */
    setScaleY(val) {
        this._scaleY = val;

        return this;
    }

    /**
     *
     * @method Sprite#setSrcHeight
     * @param  {Integer} val The srcHeight value
     * @return {Sprite}
     */
    setSrcHeight(val) {
        this._srcHeight = val;

        return this;
    }

    /**
     *
     * @method Sprite#setSrcWidth
     * @param  {Integer} val The srcWidth value
     * @return {Sprite}
     */
    setSrcWidth(val) {
        this._srcWidth = val;

        return this;
    }

    /**
     *
     * @method Sprite#setSrcX
     * @param  {Integer} val The srcX value
     * @return {Sprite}
     */
    setSrcX(val) {
        this._srcX = val;

        return this;
    }

    /**
     *
     * @method Sprite#setSrcY
     * @param  {Integer} val The srcY value
     * @return {Sprite}
     */
    setSrcY(val) {
        this._srcY = val;

        return this;
    }

    /**
     *
     * @method Sprite#setWidth
     * @param  {Integer} val The width value
     * @return {Sprite}
     */
    setWidth(val) {
        this._width = val;

        return this;
    }

    /**
     *
     * @method Sprite#setComposite
     * @param  {Integer} val The x value
     * @return {Sprite}
     */
    setX(val) {
        this._x = val;

        return this;
    }

    /**
     *
     * @method Sprite#setY
     * @param  {Integer} val The y value
     * @return {Sprite}
     */
    setY(val) {
        this._y = val;

        return this;
    }

    /**
     * Add/Subtract current x/y values. Assign any non-number to leave value the same.
     *
     * @method Sprite#translate
     * @param {Integer} [x]
     * @param {Integer} [y]
     * @returns {Sprite}
     */
    translate(x, y) {
        if (typeof x === 'number') {
            this._x += x;
        }

        if (typeof y === 'number') {
            this._y += y;
        }

        return this;
    }
}

/**
 * @member Sprite._compositeDefault
 * @type {String}
 */
Sprite._compositeDefault = 'source-over';

export default Sprite;