phaser/src/gameobjects/domelement/DOMElement.js

363 lines
8.9 KiB
JavaScript
Raw Normal View History

/**
* @author Richard Davey <rich@photonstorm.com>
2019-01-15 16:20:22 +00:00
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../utils/Class');
var Components = require('../components');
var DOMElementRender = require('./DOMElementRender');
2018-07-18 23:22:38 +00:00
var GameObject = require('../GameObject');
var IsPlainObject = require('../../utils/object/IsPlainObject');
2018-08-08 14:01:29 +00:00
var RemoveFromDOM = require('../../dom/RemoveFromDOM');
2018-07-18 23:22:38 +00:00
var Vector4 = require('../../math/Vector4');
/**
* @classdesc
* [description]
*
* @class DOMElement
* @extends Phaser.GameObjects.GameObject
2018-10-10 09:49:13 +00:00
* @memberof Phaser.GameObjects
* @constructor
* @since 3.17.0
*
* @extends Phaser.GameObjects.Components.Alpha
* @extends Phaser.GameObjects.Components.BlendMode
2018-07-18 23:22:38 +00:00
* @extends Phaser.GameObjects.Components.ComputedSize
* @extends Phaser.GameObjects.Components.Depth
* @extends Phaser.GameObjects.Components.Origin
* @extends Phaser.GameObjects.Components.ScrollFactor
* @extends Phaser.GameObjects.Components.Transform
* @extends Phaser.GameObjects.Components.Visible
*
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
* @param {number} x - The horizontal position of this DOM Element in the world.
* @param {number} y - The vertical position of this DOM Element in the world.
* @param {(HTMLElement|string)} [element] - An existing DOM element, or a string. If a string starting with a # it will do a `getElementById` look-up on the string (minus the hash). Without a hash, it represents the type of element to create, i.e. 'div'.
* @param {(string|any)} [style] - If a string, will be set directly as the elements `style` property value. If a plain object, will be iterated and the values transferred. In both cases the values replacing whatever CSS styles may have been previously set.
* @param {string} [innerText] - If given, will be set directly as the elements `innerText` property value, replacing whatever was there before.
*/
var DOMElement = new Class({
Extends: GameObject,
Mixins: [
Components.Alpha,
Components.BlendMode,
2018-07-18 23:22:38 +00:00
Components.ComputedSize,
Components.Depth,
2018-07-18 23:22:38 +00:00
Components.Origin,
Components.ScrollFactor,
Components.Transform,
Components.Visible,
DOMElementRender
],
initialize:
function DOMElement (scene, x, y, element, style, innerText)
{
GameObject.call(this, scene, 'DOMElement');
this.parent = scene.sys.game.domContainer;
this.cache = scene.sys.cache.html;
this.node;
2019-04-25 14:44:19 +00:00
this.transformOnly = false;
2018-07-18 23:22:38 +00:00
this.skewX = 0;
this.skewY = 0;
// https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d
this.rotate3d = new Vector4();
this.rotate3dAngle = 'deg';
2018-07-19 15:22:58 +00:00
this.handler = this.dispatchNativeEvent.bind(this);
2018-07-18 23:22:38 +00:00
this.setPosition(x, y);
if (typeof element === 'string')
2018-07-18 23:22:38 +00:00
{
// hash?
if (element[0] === '#')
{
this.setElement(element.substr(1), style, innerText);
}
else
{
this.createElement(element, style, innerText);
}
}
else if (element)
{
this.setElement(element, style, innerText);
2018-07-18 23:22:38 +00:00
}
},
setSkew: function (x, y)
{
if (x === undefined) { x = 0; }
if (y === undefined) { y = x; }
this.skewX = x;
this.skewY = y;
return this;
},
2018-07-19 15:22:58 +00:00
perspective: {
get: function ()
{
return parseFloat(this.parent.style.perspective);
},
set: function (value)
{
this.parent.style.perspective = value + 'px';
}
},
2018-07-18 23:22:38 +00:00
setPerspective: function (value)
{
// Sets it on the DOM Container!
this.parent.style.perspective = value + 'px';
return this;
},
2018-07-19 15:22:58 +00:00
addListener: function (events)
{
2018-07-19 15:22:58 +00:00
if (this.node)
{
2018-07-19 15:22:58 +00:00
events = events.split(' ');
for (var i = 0; i < events.length; i++)
{
this.node.addEventListener(events[i], this.handler, false);
}
}
2018-07-19 15:22:58 +00:00
return this;
},
2018-07-19 15:22:58 +00:00
removeListener: function (events)
{
if (this.node)
{
2018-07-19 15:22:58 +00:00
events = events.split(' ');
for (var i = 0; i < events.length; i++)
{
this.node.removeEventListener(events[i], this.handler);
}
}
return this;
},
dispatchNativeEvent: function (event)
{
this.emit(event.type, event);
},
createElement: function (element, style, innerText)
{
return this.setElement(document.createElement(element), style, innerText);
},
setElement: function (element, style, innerText)
{
var target;
if (typeof element === 'string')
{
target = document.getElementById(element);
}
else if (typeof element === 'object' && element.nodeType === 1)
{
target = element;
}
if (!target)
{
return;
}
this.node = target;
// style can be empty, a string or a plain object
2019-04-23 10:21:26 +00:00
if (style && IsPlainObject(style))
{
for (var key in style)
{
target.style[key] = style[key];
}
}
else if (typeof style === 'string')
{
target.style = style;
}
// Add / Override the values we need
target.style.zIndex = '0';
2018-07-18 23:42:28 +00:00
target.style.display = 'inline';
target.style.position = 'absolute';
// Node handler
2018-07-19 15:22:58 +00:00
target.phaser = this;
if (this.parent)
{
this.parent.appendChild(target);
}
2018-07-18 23:22:38 +00:00
// InnerText
if (innerText)
{
target.innerText = innerText;
}
2018-07-18 23:22:38 +00:00
var nodeBounds = target.getBoundingClientRect();
this.setSize(nodeBounds.width || 0, nodeBounds.height || 0);
return this;
},
2018-07-18 23:42:28 +00:00
createFromCache: function (key, elementType)
{
return this.createFromHTML(this.cache.get(key), elementType);
2018-07-18 23:42:28 +00:00
},
createFromHTML: function (html, elementType)
{
if (elementType === undefined) { elementType = 'div'; }
var element = document.createElement(elementType);
2018-07-19 15:22:58 +00:00
this.node = element;
element.style.zIndex = '0';
element.style.display = 'inline';
element.style.position = 'absolute';
// Node handler
element.phaser = this;
if (this.parent)
{
this.parent.appendChild(element);
}
2018-07-18 23:42:28 +00:00
element.innerHTML = html;
2018-07-19 15:22:58 +00:00
var nodeBounds = element.getBoundingClientRect();
this.setSize(nodeBounds.width || 0, nodeBounds.height || 0);
return this;
},
getChildByProperty: function (property, value)
{
if (this.node)
{
var children = this.node.querySelectorAll('*');
for (var i = 0; i < children.length; i++)
{
if (children[i][property] === value)
{
return children[i];
}
}
}
return null;
},
getChildByID: function (id)
{
return this.getChildByProperty('id', id);
},
getChildByName: function (name)
{
return this.getChildByProperty('name', name);
2018-07-18 23:42:28 +00:00
},
2019-04-23 10:21:26 +00:00
setClassName: function (className)
{
if (this.node)
{
this.node.className = className;
var nodeBounds = this.node.getBoundingClientRect();
this.setSize(nodeBounds.width, nodeBounds.height);
}
return this;
},
2018-07-18 23:22:38 +00:00
setText: function (text)
{
if (this.node)
{
this.node.innerText = text;
2018-08-08 14:01:29 +00:00
var nodeBounds = this.node.getBoundingClientRect();
this.setSize(nodeBounds.width, nodeBounds.height);
2018-07-18 23:22:38 +00:00
}
return this;
},
setHTML: function (html)
{
if (this.node)
{
this.node.innerHTML = html;
2018-08-08 14:01:29 +00:00
var nodeBounds = this.node.getBoundingClientRect();
this.setSize(nodeBounds.width, nodeBounds.height);
2018-07-18 23:22:38 +00:00
}
return this;
},
2018-07-19 15:22:58 +00:00
/**
* Compares the renderMask with the renderFlags to see if this Game Object will render or not.
*
* DOMElements always return `true` as they need to still set values during the render pass, even if not visible.
*
* @method Phaser.GameObjects.DOMElement#willRender
* @since 3.12.0
*
* @return {boolean} True if the Game Object should be rendered, otherwise false.
*/
willRender: function ()
{
return true;
},
2018-07-18 23:22:38 +00:00
destroy: function ()
{
2018-08-08 14:01:29 +00:00
RemoveFromDOM(this.node);
}
});
module.exports = DOMElement;