API Docs for: 1.0.1

File: js\grape\game\abstract-view.js

define(['../class', '../env', '../game/system', '../utils'], function (Class, Env, System, Utils) {
    function propValue(prop, max) {
        if (typeof (prop) === 'function') {
            return prop(max);
        }
        if (parseFloat(prop) + '' === prop + '') { //number format
            return prop * 1;
        } else {
            return createFunction('p', 'return ' + prop.replace(/%/g, '/100*p') + ';')(max);
        }
    }

    var fnCache = {}; //params+body -> function
    var cacheOrder = []; //params+body

    function createFunction(params, body) {
        /*jslint evil: true */
        var key = params + ';' + body;
        if (!fnCache[key]) {
            if (cacheOrder.length >= 100) { //cache full
                delete fnCache[cacheOrder.shift()];
            }
            fnCache[key] = new Function(params, body);
            cacheOrder.push(key);
        }
        return fnCache[key];
    }

    //TODOv2 follow player etc.
    /**
     * Provides a viewport to the game. The dimension properties (width, height, left, top, originX, originY) are
     * calculated dynamically. You can set these properties as functions or evaluated strings, like '30%+40'.
     *
     * @class Grape.AbstractView
     * @uses Grape.System
     * @constructor
     * @param {Object} opts Initial properties
     */
    return Class('AbstractView', System, {
        init: function (opts) {
            /**
             * The width of the view. The maximum value (100%) is the container width.
             *
             * @property width
             * @type {String|Number|Function}
             * @default '100%'
             */
            this.width = '100%';
            /**
             * The height of the view. The maximum value (100%) is the container height.
             *
             * @property height
             * @type {String|Number|Function}
             * @default '100%'
             */
            this.height = '100%';
            /**
             * The left axis of the view in the container. The maximum value (100%) is the container width.
             *
             * @property left
             * @type {String|Number|Function}
             * @default 0
             */
            this.left = 0;
            /**
             * The top axis of the view in the container. The maximum value (100%) is the container height.
             *
             * @property top
             * @type {String|Number|Function}
             * @default 0
             */
            this.top = 0;
            /**
             * The horizontal origin of the view. Tells where should a point with x = view.x appear on the screen. The
             * maximum value (100%) is the width of the view.
             *
             * @property originX
             * @type {String|Number|Function}
             * @default 0
             */
            this.originX = 0;
            /**
             * The vertical origin of the view. Tells where should a point with y = view.y appear on the screen. The
             * maximum value (100%) is the height of the view.
             *
             * @property originY
             * @type {String|Number|Function}
             * @default 0
             */
            this.originY = 0;

            /**
             * The x coordinate of the showed area.
             *
             * @property x
             * @type {Number}
             * @default 0
             */
            this.x = 0;

            /**
             * The y coordinate of the showed area.
             *
             * @property y
             * @type {Number}
             * @default 0
             */
            this.y = 0;
            /* TODOv2 doc
             * The zoom level of the view.
             *
             * @property zoom
             * @type {Number}
             * @default 1
             */
            this.zoom = 1; //TODOv2 use
            /**
             * The global alpha value of the view.
             *
             * @property alpha
             * @type {number}
             * @default 1
             */
            this.alpha = 1;
            Utils.extend(this, opts);
        },
        _calculateMouse: function (mouse) {
            /**
             * Information about the mouse relative to the view.
             *
             * @property mouse
             * @type {number}
             */
            var viewX = this.mouse.view.x = mouse.x - this.getLeft();
            var viewY = this.mouse.view.y = mouse.y - this.getTop();
            this.mouse.x = viewX + this.x - this.getOriginX();
            this.mouse.y = viewY + this.y - this.getOriginY();
            this.mouse.inView = false;
            if (viewX >= 0 && viewY >= 0 && viewX < this.getWidth() && viewY < this.getHeight()) {
                this.mouse.inView = true;
                mouse.view = this;
                /**
                 * Emitted to the containing layer when the mouse position changed according to the position in the
                 * previous frame. The parameter is the view.
                 *
                 * @event mouseMoveView (layer)
                 */
                this.getLayer().emit('mouseMoveView', this);
            }
        },
        'event start': function (game) {
            var el;
            this._game = game;
            this.mouse = {
                view: {}
            };
            /* istanbul ignore else */
            if (Env.browser) {
                el = this.el = this.createDom();
                el.style.position = 'absolute';
                this.updateSize();
                this._game.getScreen().appendChild(el);
                /**
                 * This event is fired after the createDom() method is called and the DOM element is appended to the
                 * container. The parameter is the element.
                 *
                 * @event domCreated
                 */
                this.emit('domCreated', el);
            }
            this._calculateMouse(game.input.mouse);
        },
        'event stop': function () {
            /* istanbul ignore else */
            if (Env.browser) {
                this.el.parentNode.removeChild(this.el);
            }
        },
        'event renderLayer': function () {
            this.el.style.left = this.getLeft() + 'px';
            this.el.style.top = this.getTop() + 'px';
            this.el.style.opacity = this.alpha;
            this.updateSize();
        },
        'event mouseMove': function (mouse) {
            this._calculateMouse(mouse);
        },
        /**
         * This method is called in each render frame, and should be update the displayed element's width.
         * The default functionality is setting the style width and height, but for canvas it is different.
         *
         * @method updateSize
         */
        updateSize: function () {
            this.el.style.width = this.getWidth() + 'px';
            this.el.style.height = this.getHeight() + 'px';
        },
        /**
         * Returns the calculated width left.
         *
         * @method getLeft
         * @return {Number} calculated left
         */
        getLeft: function () {
            return propValue(this.left, this._game.getScreenWidth()) >> 0;
        },
        /**
         * Returns the calculated top value.
         *
         * @method getTop
         * @return {Number} calculated top
         */
        getTop: function () {
            return propValue(this.top, this._game.getScreenHeight()) >> 0;
        },
        /**
         * Returns the calculated width value.
         *
         * @method getWidth
         * @return {Number} calculated width
         */
        getWidth: function () {
            return propValue(this.width, this._game.getScreenWidth()) >> 0;
        },
        /**
         * Returns the calculated height value.
         *
         * @method getHeight
         * @return {Number} calculated height
         */
        getHeight: function () {
            return propValue(this.height, this._game.getScreenHeight()) >> 0;
        },
        /**
         * Returns the calculated originX value.
         *
         * @method getOriginX
         * @return {Number} calculated originX
         */
        getOriginX: function () {
            return propValue(this.originX, this.getWidth()) >> 0;
        },
        /**
         * Returns the calculated originY value.
         *
         * @method getOriginY
         * @return {Number} calculated originY
         */
        getOriginY: function () {
            return propValue(this.originY, this.getHeight()) >> 0;
        },
        /**
         * This abstract method should create the HTMLElement which serves
         *
         * @method createDom
         * @return {HTMLElement} Canvas
         */
        'abstract createDom': null
    });
});