var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
/**
* @module annie
*/
var annie;
(function (annie) {
/**
* Stage 表示显示 canvas 内容的整个区域,所有显示对象的顶级显示容器
* 无法以全局方式访问 Stage 对象,而是需要利用DisplayObject实例的getStage()方法进行访问
* @class annie.Stage
* @extends annie.Sprite
* @public
* @since 1.0.0
*/
var Stage = (function (_super) {
__extends(Stage, _super);
/**
* 显示对象入口函数
* @method Stage
* @param {string} rootDivId
* @param {number} desW 舞台宽
* @param {number} desH 舞台高
* @param {number} fps 刷新率
* @param {string} scaleMode 缩放模式 StageScaleMode
* @param {string} bgColor 背景颜色-1为透明
* @param {number} renderType 渲染模式0:canvas 1:webGl 2:dom
* @public
* @since 1.0.0
*/
function Stage(rootDivId, desW, desH, frameRate, scaleMode, renderType) {
if (rootDivId === void 0) { rootDivId = "annieEngine"; }
if (desW === void 0) { desW = 640; }
if (desH === void 0) { desH = 1040; }
if (frameRate === void 0) { frameRate = 30; }
if (scaleMode === void 0) { scaleMode = "fixedHeight"; }
if (renderType === void 0) { renderType = 0; }
var _this = _super.call(this) || this;
/**
* 是否阻止ios端双击后页面会往上弹的效果,因为如果阻止了,可能有些html元素出现全选框后无法取消
* 所以需要自己灵活设置,默认阻止.
* @property iosTouchendPreventDefault
* @type {boolean}
* @default true
* @since 1.0.4
* @public
*/
_this.iosTouchendPreventDefault = true;
/**
* 是否禁止引擎所在的canvas的鼠标事件或触摸事件的默认形为,默认为true是禁止的。
* @property isPreventDefaultEvent
* @since 1.0.9
* @default true
* @type {boolean}
*/
_this.isPreventDefaultEvent = true;
/**
* 整个引擎的最上层的div元素,
* 承载canvas的那个div html元素
* @property rootDiv
* @public
* @since 1.0.0
* @type {Html Div}
* @default null
*/
_this.rootDiv = null;
/**
* 当前stage所使用的渲染器
* 渲染器有两种,一种是canvas 一种是webGl
* @property renderObj
* @public
* @since 1.0.0
* @type {IRender}
* @default null
*/
_this.renderObj = null;
/**
* 渲染模式值 只读 CANVAS:0, webGl: 1
* @property renderType
* @readonly
* @public
* @since 1.0.0
* @type {number}
* @default 0
* @readonly
*/
_this.renderType = 0;
/**
* 如果值为true则暂停更新当前显示对象及所有子对象。在视觉上就相当于界面停止了,但一样能会接收鼠标事件<br/>
* 有时候背景为大量动画的一个对象时,当需要弹出一个框或者其他内容,或者模糊一个背景时可以设置此属性让<br/>
* 对象视觉暂停更新
* @property pause
* @type {boolean}
* @public
* @since 1.0.0
* @default false
*/
_this.pause = false;
/**
* 舞台在设备里截取后的可见区域,有些时候知道可见区域是非常重要的,因为这样你就可以根据舞台的可见区域做自适应了。
* @property viewRect
* @public
* @readonly
* @since 1.0.0
* @type {annie.Rectangle}
* @default {x:0,y:0,width:0,height:0}
* @readonly
* @example
* //始终让一个对象顶对齐,或者
*/
_this.viewRect = new annie.Rectangle();
/**
* 开启或关闭多点手势事件 目前仅支持两点 旋转 缩放
* @property isMultiTouch
* @since 1.0.3
* @type {boolean}
*/
_this.isMultiTouch = false;
/**
* 开启或关闭多个手指的鼠标事件 目前仅支持两点 旋转 缩放
* @property isMultiMouse
* @since 1.1.3
* @type {boolean}
*/
_this.isMultiMouse = false;
/**
* 当设备尺寸更新,或者旋转后是否自动更新舞台方向
* 端默认不开启
* @property autoSteering
* @public
* @since 1.0.0
* @type {boolean}
* @default false
*/
_this.autoSteering = false;
/**
* 当设备尺寸更新,或者旋转后是否自动更新舞台尺寸
* @property autoResize
* @public
* @since 1.0.0
* @type {boolean}
* @default false
*/
_this.autoResize = false;
/**
* 舞台的尺寸宽,也就是我们常说的设计尺寸
* @property desWidth
* @public
* @since 1.0.0
* @default 320
* @type {number}
* @readonly
*/
_this.desWidth = 0;
/**
* 舞台的尺寸高,也就是我们常说的设计尺寸
* @property desHeight
* @public
* @since 1.0.0
* @default 240
* @type {number}
* @readonly
*/
_this.desHeight = 0;
/**
* 舞台在当前设备中的真实高
* @property divHeight
* @public
* @since 1.0.0
* @default 320
* @type {number}
* @readonly
*/
_this.divHeight = 0;
/**
* 舞台在当前设备中的真实宽
* @property divWidth
* @public
* @since 1.0.0
* @default 240
* @readonly
* @type {number}
*/
_this.divWidth = 0;
/**
* 舞台的背景色
* 默认就是透明背景
* 可能设置一个颜色值改变舞台背景
* @property bgColor
* @public
* @since 1.0.0
* @type {string}
* @default "";
*/
_this.bgColor = "";
/**
* 舞台的缩放模式
* 默认为空就是无缩放的真实大小
* "noBorder" 无边框模式
* ”showAll" 显示所有内容
* “fixedWidth" 固定宽
* ”fixedHeight" 固定高
* @property scaleMode
* @public
* @since 1.0.0
* @default "onScale"
* @type {string}
* @example
* //动态更改stage的对齐方式示例
* //以下代码放到一个舞台的显示对象的构造函数中
* let s=this;
* s.addEventListener(annie.Event.ADD_TO_STAGE,function(e){
* let i=0;
* s.stage.addEventListener(annie.MouseEvent.CLICK,function(e){
* let aList=[annie.StageScaleMode.EXACT_FIT,annie.StageScaleMode.NO_BORDER,annie.StageScaleMode.NO_SCALE,annie.StageScaleMode.SHOW_ALL,annie.StageScaleMode.FIXED_WIDTH,annie.StageScaleMode.FIXED_HEIGHT]
* let state=e.currentTarget;
* state.scaleMode=aList[i];
* state.resize();
* if(i>5){i=0;}
* }
* }
*
*/
_this.scaleMode = "onScale";
/**
* 原始为60的刷新速度时的计数器
* @property _flush
* @private
* @since 1.0.0
* @default 0
* @type {number}
*/
_this._flush = 0;
/**
* 当前的刷新次数计数器
* @property _currentFlush
* @private
* @since 1.0.0
* @default 0
* @type {number}
*/
_this._currentFlush = 0;
_this._lastDpList = {};
_this._rid = -1;
_this._floatDisplayList = [];
/**
* 这个是鼠标事件的MouseEvent对象池,因为如果用户有监听鼠标事件,如果不建立对象池,那每一秒将会new Fps个数的事件对象,影响性能
* @type {Array}
* @private
*/
_this._ml = [];
/**
* 这个是事件中用到的Point对象池,以提高性能
* @type {Array}
* @private
*/
_this._mp = [];
//每一个手指事件的对象池
_this._mouseDownPoint = {};
/**
* html的鼠标或单点触摸对应的引擎事件类型名
* @type {{mousedown: string, mouseup: string, mousemove: string, touchstart: string, touchmove: string, touchend: string}}
* @private
*/
_this._mouseEventTypes = {
mousedown: "onMouseDown",
mouseup: "onMouseUp",
mousemove: "onMouseMove",
touchstart: "onMouseDown",
touchmove: "onMouseMove",
touchend: "onMouseUp"
};
_this.muliPoints = [];
/**
* 当document有鼠标或触摸事件时调用
* @param e
*/
_this._mP1 = new annie.Point();
_this._mP2 = new annie.Point();
_this.onMouseEvent = function (e) {
//检查是否有
var s = this;
if (s.isMultiTouch && e.targetTouches) {
if (e.targetTouches.length == 2) {
//求角度和距离
s._mP1.x = e.targetTouches[0].clientX - e.target.offsetLeft;
s._mP1.y = e.targetTouches[0].clientY - e.target.offsetTop;
s._mP2.x = e.targetTouches[1].clientX - e.target.offsetLeft;
s._mP2.y = e.targetTouches[1].clientY - e.target.offsetTop;
var angle = Math.atan2(s._mP1.y - s._mP2.y, s._mP1.x - s._mP2.x) / Math.PI * 180;
var dis = annie.Point.distance(s._mP1, s._mP2);
s.muliPoints.push({ p1: s._mP1, p2: s._mP2, angle: angle, dis: dis });
if (s.muliPoints.length >= 2) {
//如果有事件,抛事件
if (!s._touchEvent) {
s._touchEvent = new annie.TouchEvent(annie.TouchEvent.ON_MULTI_TOUCH);
s._touchEvent.target = s;
}
var len = s.muliPoints.length;
s._touchEvent.rotate = (s.muliPoints[len - 1].angle - s.muliPoints[len - 2].angle) * 2;
s._touchEvent.scale = (s.muliPoints[len - 1].dis - s.muliPoints[len - 2].dis) / (s.divHeight > s.divWidth ? s.desWidth : s.desHeight) * 4;
s._touchEvent.clientPoint1.x = s.muliPoints[len - 1].p1.x * annie.devicePixelRatio;
s._touchEvent.clientPoint2.x = s.muliPoints[len - 1].p2.x * annie.devicePixelRatio;
s._touchEvent.clientPoint1.y = s.muliPoints[len - 1].p1.y * annie.devicePixelRatio;
s._touchEvent.clientPoint2.y = s.muliPoints[len - 1].p2.y * annie.devicePixelRatio;
s.dispatchEvent(s._touchEvent);
s.muliPoints = [];
}
}
else {
s.muliPoints = [];
}
}
var isMulti = s.isMultiMouse || (e.targetTouches && e.targetTouches.length > 1);
//检查mouse或touch事件是否有,如果有的话,就触发事件函数
if (!isMulti && annie.EventDispatcher._totalMEC > 0) {
var points = void 0;
var item = s._mouseEventTypes[e.type];
var events = void 0;
var event_1;
//stageMousePoint
var sp = void 0;
//localPoint;
var lp = void 0;
//clientPoint
var cp = void 0;
//事件个数
var eLen = void 0;
var identifier = void 0;
if (annie.osType == "pc") {
e.identifier = 0;
points = [e];
}
else {
points = e.changedTouches;
}
for (var o = 0; o < points.length; o++) {
eLen = 0;
events = [];
identifier = "m" + points[o].identifier;
if (s._mp.length > 0) {
cp = s._mp.shift();
}
else {
cp = new annie.Point();
}
cp.x = (points[o].clientX - points[o].target.offsetLeft) * annie.devicePixelRatio;
cp.y = (points[o].clientY - points[o].target.offsetTop) * annie.devicePixelRatio;
//这个地方检查是所有显示对象列表里是否有添加任何鼠标或触碰事件,有的话就检测,没有的话就算啦。
sp = s.globalToLocal(cp, annie.DisplayObject._bp);
if (annie.EventDispatcher.getMouseEventCount() > 0) {
if (!s._ml[eLen]) {
event_1 = new annie.MouseEvent(item);
s._ml[eLen] = event_1;
}
else {
event_1 = s._ml[eLen];
event_1.type = item;
}
events.push(event_1);
s._initMouseEvent(event_1, cp, sp, identifier);
eLen++;
}
if (item == "onMouseDown") {
s._mouseDownPoint[identifier] = cp;
//清空上次存在的显示列表
}
else if (item == "onMouseUp") {
if (s._mouseDownPoint[identifier]) {
if (annie.Point.distance(s._mouseDownPoint[identifier], cp) < 20) {
//click事件
//这个地方检查是所有显示对象列表里是否有添加对应的事件
if (annie.EventDispatcher.getMouseEventCount("onMouseClick") > 0) {
if (!s._ml[eLen]) {
event_1 = new annie.MouseEvent("onMouseClick");
s._ml[eLen] = event_1;
}
else {
event_1 = s._ml[eLen];
event_1.type = "onMouseClick";
}
events.push(event_1);
s._initMouseEvent(event_1, cp, sp, identifier);
eLen++;
}
}
}
}
if (eLen > 0) {
//证明有事件那么就开始遍历显示列表。就算有多个事件也不怕,因为坐标点相同,所以只需要遍历一次
var d = s.hitTestPoint(cp, true);
var displayList = [];
if (d) {
//证明有点击到事件,然后从最底层追上来,看看一路是否有人添加过mouse或touch事件,还要考虑mousechildren和阻止事件方法
//找出真正的target,因为有些父级可能会mouseChildren=false;
while (d) {
if (d["mouseChildren"] === false) {
//丢掉之前的层级,因为根本没用了
displayList.length = 0;
}
displayList.push(d);
d = d.parent;
}
}
else {
displayList.push(s);
}
var len = displayList.length;
displayList.reverse();
for (var i = 0; i < len; i++) {
d = displayList[i];
for (var j = 0; j < eLen; j++) {
if (events[j]["_pd"] === false) {
if (d.hasEventListener(events[j].type)) {
events[j].currentTarget = d;
events[j].target = displayList[len - 1];
lp = d.globalToLocal(cp, annie.DisplayObject._bp);
events[j].localX = lp.x;
events[j].localY = lp.y;
d.dispatchEvent(events[j]);
}
}
}
}
//最后要和上一次的遍历者对比下,如果不相同则要触发onMouseOver和onMouseOut
if (item != "onMouseDown") {
if (annie.EventDispatcher.getMouseEventCount("onMouseOver") > 0 || annie.EventDispatcher.getMouseEventCount("onMouseOut") > 0) {
if (s._lastDpList[identifier]) {
//从第二个开始,因为第一个对象始终是stage顶级对象
var len1 = s._lastDpList[identifier].length;
var len2 = displayList.length;
len = len1 > len2 ? len1 : len2;
var isDiff = false;
var overEvent = void 0;
var outEvent = void 0;
for (var i = 1; i < len; i++) {
if (!isDiff) {
if (s._lastDpList[identifier][i] != displayList[i]) {
//好就是这里,需要确定哪些有onMouseOver,哪些有onMouseOut
isDiff = true;
if (!s._ml[eLen]) {
overEvent = new annie.MouseEvent("onMouseOver");
s._ml[eLen] = overEvent;
}
else {
overEvent = s._ml[eLen];
overEvent.type = "onMouseOver";
}
s._initMouseEvent(overEvent, cp, sp, identifier);
eLen++;
if (!s._ml[eLen]) {
outEvent = new annie.MouseEvent("onMouseOut");
s._ml[eLen] = outEvent;
}
else {
outEvent = s._ml[eLen];
outEvent.type = "onMouseOut";
}
s._initMouseEvent(outEvent, cp, sp, identifier);
}
}
if (isDiff) {
if (s._lastDpList[identifier][i]) {
//触发onMouseOut事件
if (outEvent["_pd"] === false) {
d = s._lastDpList[identifier][i];
if (d.hasEventListener("onMouseOut")) {
outEvent.currentTarget = d;
outEvent.target = s._lastDpList[identifier][len1 - 1];
lp = d.globalToLocal(cp, annie.DisplayObject._bp);
outEvent.localX = lp.x;
outEvent.localY = lp.y;
d.dispatchEvent(outEvent);
}
}
}
if (displayList[i]) {
//触发onMouseOver事件
if (overEvent["_pd"] === false) {
d = displayList[i];
if (d.hasEventListener("onMouseOver")) {
overEvent.currentTarget = d;
overEvent.target = displayList[len2 - 1];
lp = d.globalToLocal(cp, annie.DisplayObject._bp);
overEvent.localX = lp.x;
overEvent.localY = lp.y;
d.dispatchEvent(overEvent);
}
}
}
}
}
}
}
s._mp.push(cp);
}
//判断是否有drag的显示对象
var sd = Stage._dragDisplay;
if (sd && sd.stage && sd.parent) {
var x1 = sd.x, y1 = sd.y;
lp = sd.parent.globalToLocal(cp, annie.DisplayObject._bp);
if (!sd._isDragCenter) {
if (sd._lastDragPoint.x != Number.MAX_VALUE) {
x1 += lp.x - sd._lastDragPoint.x;
y1 += lp.y - sd._lastDragPoint.y;
}
sd._lastDragPoint.x = lp.x;
sd._lastDragPoint.y = lp.y;
}
else {
x1 = lp.x;
y1 = lp.y;
}
lp.x = x1;
lp.y = y1;
if (sd._dragBounds.width != 0) {
if (!sd._dragBounds.isPointIn(lp)) {
if (x1 < sd._dragBounds.x) {
x1 = sd._dragBounds.x;
}
else if (x1 > sd._dragBounds.x + sd._dragBounds.width) {
x1 = sd._dragBounds.x + sd._dragBounds.width;
}
if (y1 < sd._dragBounds.y) {
y1 = sd._dragBounds.y;
}
else if (y1 > sd._dragBounds.y + sd._dragBounds.height) {
y1 = sd._dragBounds.y + sd._dragBounds.height;
}
}
}
sd.x = x1;
sd.y = y1;
}
if (item == "onMouseUp") {
if (sd) {
sd._lastDragPoint.x = Number.MAX_VALUE;
sd._lastDragPoint.y = Number.MAX_VALUE;
}
delete s._mouseDownPoint[identifier];
delete s._lastDpList[identifier];
}
else {
s._lastDpList[identifier] = displayList;
}
}
}
}
if (e.target.id == "_a2x_canvas") {
if (s.isPreventDefaultEvent) {
if ((e.type == "touchend") && (annie.osType == "ios") && (s.iosTouchendPreventDefault)) {
e.preventDefault();
}
if ((e.type == "touchmove") || (e.type == "touchstart" && annie.osType == "android")) {
e.preventDefault();
}
}
}
if (s._cp) {
s.update();
}
};
/**
* 设置舞台的对齐模式
*/
_this.setAlign = function () {
var s = this;
var divH = s.divHeight * annie.devicePixelRatio;
var divW = s.divWidth * annie.devicePixelRatio;
var desH = s.desHeight;
var desW = s.desWidth;
s.anchorX = desW / 2;
s.anchorY = desH / 2;
//设备是否为竖屏
var isDivH = divH > divW;
//内容是否为竖屏内容
var isDesH = desH > desW;
var scaleY = 1;
var scaleX = 1;
s.x = (divW - desW) / 2;
s.y = (divH - desH) / 2;
if (s.autoSteering) {
if (isDesH != isDivH) {
var d = divH;
divH = divW;
divW = d;
}
}
if (s.scaleMode != "noScale") {
scaleY = divH / desH;
scaleX = divW / desW;
switch (s.scaleMode) {
case "noBorder":
if (scaleX > scaleY) {
scaleY = scaleX;
}
else {
scaleX = scaleY;
}
break;
case "showAll":
if (scaleX < scaleY) {
scaleY = scaleX;
}
else {
scaleX = scaleY;
}
break;
case "fixedWidth":
scaleY = scaleX;
break;
case "fixedHeight":
scaleX = scaleY;
break;
}
}
s.scaleX = scaleX;
s.scaleY = scaleY;
// s.viewRect=new annie.Rectangle();
s.viewRect.x = (desW - divW / scaleX) / 2;
s.viewRect.y = (desH - divH / scaleY) / 2;
s.viewRect.width = desW - s.viewRect.x * 2;
s.viewRect.height = desH - s.viewRect.y * 2;
if (s.autoSteering) {
if (isDesH == isDivH) {
s.rotation = 0;
}
else {
if (desH > desW) {
s.rotation = -90;
}
else {
s.rotation = 90;
}
}
}
else {
s.rotation = 0;
}
};
/**
* 当舞台尺寸发生改变时,如果stage autoResize 为 true,则此方法会自己调用;
* 如果设置stage autoResize 为 false 你需要手动调用此方法以更新界面.
* 不管autoResize 的状态是什么,你只要侦听 了stage 的 annie.Event.RESIZE 事件
* 都可以接收到舞台变化的通知。
* @method resize
* @public
* @since 1.0.0
*/
_this.resize = function () {
var s = this;
var whObj = s.getRootDivWH(s.rootDiv);
s._UI.UM = true;
s.divHeight = whObj.h;
s.divWidth = whObj.w;
s.renderObj.reSize();
s.setAlign();
s.update();
};
var s = _this;
_this._instanceType = "annie.Stage";
s.stage = _this;
var resizeEvent = "resize";
s.name = "stageInstance_" + s.instanceId;
var div = document.getElementById(rootDivId);
s.renderType = renderType;
s.desWidth = desW;
s.desHeight = desH;
s.rootDiv = div;
s.setFrameRate(frameRate);
s.scaleMode = scaleMode;
s.anchorX = desW / 2;
s.anchorY = desH / 2;
//目前具支持canvas
s.renderObj = new annie.CanvasRender(s);
/* webgl 直到对2d的支持非常成熟了再考虑开启
if (renderType == 0) {
//canvas
s.renderObj = new CanvasRender(s);
} else {
//webgl
s.renderObj = new WGRender(s);
}*/
s.renderObj.init();
window.addEventListener(resizeEvent, function (e) {
clearTimeout(s._rid);
s._rid = setTimeout(function () {
if (s.autoResize) {
s.resize();
}
var event = new annie.Event("onResize");
s.dispatchEvent(event);
}, 300);
});
setTimeout(function () {
s.resize();
//同时添加到主更新循环中
Stage.addUpdateObj(s);
//告诉大家我初始化完成
//判断debug,如果debug等于true并且之前没有加载过则加载debug所需要的js文件
if (annie.debug && !Stage._isLoadedVConsole) {
var script_1 = document.createElement("script");
script_1.onload = function () {
s.dispatchEvent(new annie.Event("onInitStage"));
script_1.onload = null;
};
document.head.appendChild(script_1);
script_1.src = "libs/vConsole.min.js";
}
else {
s.dispatchEvent(new annie.Event("onInitStage"));
}
}, 100);
// let rc = s.renderObj.rootContainer;
var rc = s.rootDiv;
var mouseEvent = s.onMouseEvent.bind(s);
if (annie.osType != "pc") {
rc.addEventListener("touchstart", mouseEvent, false);
rc.addEventListener('touchmove', mouseEvent, false);
rc.addEventListener('touchend', mouseEvent, false);
}
else {
rc.addEventListener("mousedown", mouseEvent, false);
rc.addEventListener('mousemove', mouseEvent, false);
rc.addEventListener('mouseup', mouseEvent, false);
}
return _this;
}
/**
* 重写刷新
* @method update
* @public
* @param isDrawUpdate 不是因为渲染目的而调用的更新,比如有些时候的强制刷新 默认为true
* @since 1.0.0
*/
Stage.prototype.update = function (isDrawUpdate) {
if (isDrawUpdate === void 0) { isDrawUpdate = false; }
var s = this;
if (!s.pause) {
_super.prototype.update.call(this, isDrawUpdate);
var sf = s._floatDisplayList;
var len = sf.length;
for (var i = 0; i < len; i++) {
sf[i].updateStyle();
}
}
};
/**
* 渲染函数
* @method render
* @param renderObj
*/
Stage.prototype.render = function (renderObj) {
var s = this;
if (!s.pause) {
renderObj.begin();
_super.prototype.render.call(this, renderObj);
}
};
/**
* 刷新mouse或者touch事件
* @private
*/
Stage.prototype._initMouseEvent = function (event, cp, sp, identifier) {
event["_pd"] = false;
event.clientX = cp.x;
event.clientY = cp.y;
event.stageX = sp.x;
event.stageY = sp.y;
event.identifier = identifier;
};
/**
* 循环刷新页面的函数
*/
Stage.prototype.flush = function () {
var s = this;
if (s._flush == 0) {
s.update(true);
s.render(s.renderObj);
}
else {
//将更新和渲染分放到两个不同的时间更新值来执行,这样可以减轻cpu同时执行的压力。
if (s._currentFlush == 0) {
s.update(true);
s.render(s.renderObj);
s._currentFlush = s._flush;
}
else {
// if (s._currentFlush == s._flush) {
// s.render(s.renderObj);
// }
s._currentFlush--;
}
}
};
/**
* 引擎的刷新率,就是一秒中执行多少次刷新
* @method setFrameRate
* @param {number} fps 最好是60的倍数如 1 2 3 6 10 12 15 20 30 60
* @since 1.0.0
* @public
*/
Stage.prototype.setFrameRate = function (fps) {
var s = this;
s._flush = 60 / fps - 1 >> 0;
if (s._flush < 0) {
s._flush = 0;
}
};
/**
* 引擎的刷新率,就是一秒中执行多少次刷新
* @method getFrameRate
* @since 1.0.0
* @public
*/
Stage.prototype.getFrameRate = function () {
return 60 / (this._flush + 1);
};
/**
* 获取引擎所在的div宽高
* @method getRootDivWH
* @public
* @since 1.0.0
* @param {HTMLDivElement} div
* @returns {{w: number, h: number}}
*/
Stage.prototype.getRootDivWH = function (div) {
var sw = div.style.width;
var sh = div.style.height;
var iw = document.body.clientWidth;
var ih = document.body.clientHeight;
var vW = parseInt(sw);
var vH = parseInt(sh);
if (vW.toString() == "NaN") {
vW = iw;
}
else {
if (sw.indexOf("%") > 0) {
vW *= iw / 100;
}
}
if (vH.toString() == "NaN") {
vH = ih;
}
else {
if (sh.indexOf("%") > 0) {
vH *= ih / 100;
}
}
return { w: vW, h: vH };
};
/**
* 当一个stage不再需要使用,或者要从浏览器移除之前,请先停止它,避免内存泄漏
* @method kill
* @since 1.0.0
* @public
*/
Stage.prototype.kill = function () {
Stage.removeUpdateObj(this);
};
Stage.prototype.getBounds = function () {
return this.viewRect;
};
/**
* 刷新所有定时器
* @static
* @private
* @since 1.0.0
* @method flushAll
*/
Stage.flushAll = function () {
var len = Stage.allUpdateObjList.length;
for (var i = 0; i < len; i++) {
Stage.allUpdateObjList[i] && Stage.allUpdateObjList[i].flush();
}
requestAnimationFrame(Stage.flushAll);
};
/**
* 添加一个刷新对象,这个对象里一定要有一个 flush 函数。
* 因为一但添加,这个对象的 flush 函数会以stage的fps间隔调用
* 如,你的stage是30fps 那么你这个对象的 flush 函数1秒会调用30次。
* @method addUpdateObj
* @param target 要循化调用 flush 函数的对象
* @public
* @static
* @since
*/
Stage.addUpdateObj = function (target) {
var isHave = false;
var len = Stage.allUpdateObjList.length;
for (var i = 0; i < len; i++) {
if (Stage.allUpdateObjList[i] === target) {
isHave = true;
break;
}
}
if (!isHave) {
Stage.allUpdateObjList.unshift(target);
}
};
/**
* 移除掉已经添加的循环刷新对象
* @method removeUpdateObj
* @param target
* @public
* @static
* @since 1.0.0
*/
Stage.removeUpdateObj = function (target) {
var len = Stage.allUpdateObjList.length;
for (var i = 0; i < len; i++) {
if (Stage.allUpdateObjList[i] === target) {
Stage.allUpdateObjList.splice(i, 1);
break;
}
}
};
Stage._dragDisplay = null;
/**
* 上一次鼠标或触碰经过的显示对象列表
* @type {Array}
* @private
*/
Stage._isLoadedVConsole = false;
/**
* 要循环调用 flush 函数对象列表
* @method allUpdateObjList
* @static
* @since 1.0.0
* @type {Array}
*/
Stage.allUpdateObjList = [];
return Stage;
}(annie.Sprite));
annie.Stage = Stage;
})(annie || (annie = {}));