canvas2djs
Version:
HTML5 canvas based game engine
1,494 lines (1,447 loc) • 177 kB
JavaScript
/**
* canvas2djs v2.6.3
* Copyright (c) 2013-present Todd Fon <tilfon@live.com>
* All rights reserved.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define('canvas2djs', ['exports'], factory) :
(factory((global.canvas2d = global.canvas2d || {})));
}(this, (function (exports) { 'use strict';
var Keys = {
MOUSE_LEFT: 1,
MOUSE_MID: 2,
MOUSE_RIGHT: 3,
BACKSPACE: 8,
TAB: 9,
NUM_CENTER: 12,
ENTER: 13,
RETURN: 13,
SHIFT: 16,
CTRL: 17,
ALT: 18,
PAUSE: 19,
CAPS_LOCK: 20,
ESC: 27,
ESCAPE: 27,
SPACE: 32,
PAGE_UP: 33,
PAGE_DOWN: 34,
END: 35,
HOME: 36,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
PRINT_SCREEN: 44,
INSERT: 45,
DELETE: 46,
ZERO: 48,
ONE: 49,
TWO: 50,
THREE: 51,
FOUR: 52,
FIVE: 53,
SIX: 54,
SEVEN: 55,
EIGHT: 56,
NINE: 57,
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
G: 71,
H: 72,
I: 73,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
Q: 81,
R: 82,
S: 83,
T: 84,
U: 85,
V: 86,
W: 87,
X: 88,
Y: 89,
Z: 90,
CONTEXT_MENU: 93,
NUM0: 96,
NUM1: 97,
NUM2: 98,
NUM3: 99,
NUM4: 100,
NUM5: 101,
NUM6: 102,
NUM7: 103,
NUM8: 104,
NUM9: 105,
NUM_MULTIPLY: 106,
NUM_PLUS: 107,
NUM_MINUS: 109,
NUM_PERIOD: 110,
NUM_DIVISION: 111,
F1: 112,
F2: 113,
F3: 114,
F4: 115,
F5: 116,
F6: 117,
F7: 118,
F8: 119,
F9: 120,
F10: 121,
F11: 122,
F12: 123
};
var Tween = {
easeInQuad: function (pos) {
return Math.pow(pos, 2);
},
easeOutQuad: function (pos) {
return -(Math.pow((pos - 1), 2) - 1);
},
easeInOutQuad: function (pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 2);
}
return -0.5 * ((pos -= 2) * pos - 2);
},
easeInCubic: function (pos) {
return Math.pow(pos, 3);
},
easeOutCubic: function (pos) {
return (Math.pow((pos - 1), 3) + 1);
},
easeInOutCubic: function (pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 3);
}
return 0.5 * (Math.pow((pos - 2), 3) + 2);
},
easeInQuart: function (pos) {
return Math.pow(pos, 4);
},
easeOutQuart: function (pos) {
return -(Math.pow((pos - 1), 4) - 1);
},
easeInOutQuart: function (pos) {
if ((pos /= 0.5) < 1)
return 0.5 * Math.pow(pos, 4);
return -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
},
easeInQuint: function (pos) {
return Math.pow(pos, 5);
},
easeOutQuint: function (pos) {
return (Math.pow((pos - 1), 5) + 1);
},
easeInOutQuint: function (pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 5);
}
return 0.5 * (Math.pow((pos - 2), 5) + 2);
},
easeInSine: function (pos) {
return -Math.cos(pos * (Math.PI / 2)) + 1;
},
easeOutSine: function (pos) {
return Math.sin(pos * (Math.PI / 2));
},
easeInOutSine: function (pos) {
return (-.5 * (Math.cos(Math.PI * pos) - 1));
},
easeInExpo: function (pos) {
return (pos == 0) ? 0 : Math.pow(2, 10 * (pos - 1));
},
easeOutExpo: function (pos) {
return (pos == 1) ? 1 : -Math.pow(2, -10 * pos) + 1;
},
easeInOutExpo: function (pos) {
if (pos == 0)
return 0;
if (pos == 1)
return 1;
if ((pos /= 0.5) < 1)
return 0.5 * Math.pow(2, 10 * (pos - 1));
return 0.5 * (-Math.pow(2, -10 * --pos) + 2);
},
easeInCirc: function (pos) {
return -(Math.sqrt(1 - (pos * pos)) - 1);
},
easeOutCirc: function (pos) {
return Math.sqrt(1 - Math.pow((pos - 1), 2));
},
easeInOutCirc: function (pos) {
if ((pos /= 0.5) < 1)
return -0.5 * (Math.sqrt(1 - pos * pos) - 1);
return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1);
},
easeOutBounce: function (pos) {
if ((pos) < (1 / 2.75)) {
return (7.5625 * pos * pos);
}
else if (pos < (2 / 2.75)) {
return (7.5625 * (pos -= (1.5 / 2.75)) * pos + .75);
}
else if (pos < (2.5 / 2.75)) {
return (7.5625 * (pos -= (2.25 / 2.75)) * pos + .9375);
}
else {
return (7.5625 * (pos -= (2.625 / 2.75)) * pos + .984375);
}
},
easeInBack: function (pos) {
var s = 1.70158;
return (pos) * pos * ((s + 1) * pos - s);
},
easeOutBack: function (pos) {
var s = 1.70158;
return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1;
},
easeInOutBack: function (pos) {
var s = 1.70158;
if ((pos /= 0.5) < 1)
return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));
return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);
},
elastic: function (pos) {
return -1 * Math.pow(4, -8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1;
},
swingFromTo: function (pos) {
var s = 1.70158;
return ((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) :
0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);
},
swingFrom: function (pos) {
var s = 1.70158;
return pos * pos * ((s + 1) * pos - s);
},
swingTo: function (pos) {
var s = 1.70158;
return (pos -= 1) * pos * ((s + 1) * pos + s) + 1;
},
bounce: function (pos) {
if (pos < (1 / 2.75)) {
return (7.5625 * pos * pos);
}
else if (pos < (2 / 2.75)) {
return (7.5625 * (pos -= (1.5 / 2.75)) * pos + .75);
}
else if (pos < (2.5 / 2.75)) {
return (7.5625 * (pos -= (2.25 / 2.75)) * pos + .9375);
}
else {
return (7.5625 * (pos -= (2.625 / 2.75)) * pos + .984375);
}
},
bouncePast: function (pos) {
if (pos < (1 / 2.75)) {
return (7.5625 * pos * pos);
}
else if (pos < (2 / 2.75)) {
return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + .75);
}
else if (pos < (2.5 / 2.75)) {
return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + .9375);
}
else {
return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + .984375);
}
},
easeFromTo: function (pos) {
if ((pos /= 0.5) < 1)
return 0.5 * Math.pow(pos, 4);
return -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
},
easeFrom: function (pos) {
return Math.pow(pos, 4);
},
easeTo: function (pos) {
return Math.pow(pos, 0.25);
},
linear: function (pos) {
return pos;
},
sinusoidal: function (pos) {
return (-Math.cos(pos * Math.PI) / 2) + 0.5;
},
reverse: function (pos) {
return 1 - pos;
},
mirror: function (pos, transition) {
transition = transition || this.sinusoidal;
if (pos < 0.5)
return transition(pos * 2);
else
return transition(1 - (pos - 0.5) * 2);
},
flicker: function (pos) {
var pos = pos + (Math.random() - 0.5) / 5;
return this.sinusoidal(pos < 0 ? 0 : pos > 1 ? 1 : pos);
},
wobble: function (pos) {
return (-Math.cos(pos * Math.PI * (9 * pos)) / 2) + 0.5;
},
pulse: function (pos, pulses) {
return (-Math.cos((pos * ((pulses || 5) - .5) * 2) * Math.PI) / 2) + .5;
},
blink: function (pos, blinks) {
return Math.round(pos * (blinks || 5)) % 2;
},
spring: function (pos) {
return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
},
none: function (pos) {
return 0;
},
full: function (pos) {
return 1;
}
};
var CanvasSource = (function () {
function CanvasSource() {
this.isIdle = false;
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d');
this.width = this.canvas.width;
this.height = this.canvas.height;
}
CanvasSource.create = function () {
var instance;
var instanceList = this.instanceList;
for (var i = 0; instance = instanceList[i]; i++) {
if (instance.isIdle) {
instance.isIdle = false;
this.activeCount += 1;
return instance;
}
}
if (!instance) {
instance = new CanvasSource();
instanceList.push(instance);
}
this.activeCount += 1;
return instance;
};
CanvasSource.prototype.setSize = function (width, height) {
this.canvas.width = this.width = width;
this.canvas.height = this.height = height;
};
CanvasSource.prototype.clear = function () {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};
CanvasSource.prototype.recycle = function () {
CanvasSource.activeCount -= 1;
this.setSize(0, 0);
this.isIdle = true;
};
return CanvasSource;
}());
CanvasSource.instanceList = [];
CanvasSource.activeCount = 0;
/**
* Sprite texture
*/
var Texture = (function () {
function Texture(source, sourceRect, textureRect) {
this._readyCallbacks = [];
this._gridSourceCache = {};
this._gridSourceCount = 0;
/**
* Texture resource loading state
*/
this.ready = false;
this.width = 0;
this.height = 0;
var name = getCacheKey(source, sourceRect, textureRect);
if (Texture.textureCache[name]) {
return Texture.textureCache[name];
}
if (typeof source === 'string') {
this._createByPath(source, sourceRect, textureRect, Texture.retryTimes);
}
else if ((source instanceof HTMLImageElement) || (source instanceof HTMLCanvasElement)) {
this._createByImage(source, sourceRect, textureRect);
}
else {
throw new Error("Invalid texture source");
}
if (name) {
this.name = name;
Texture.textureCache[name] = this;
}
}
Texture.create = function (source, sourceRect, textureRect) {
var name = getCacheKey(source, sourceRect, textureRect);
if (name && this.textureCache[name]) {
return this.textureCache[name];
}
return new Texture(source, sourceRect, textureRect);
};
Texture.getByName = function (name) {
return this.textureCache[name];
};
/**
* 缓存Texture实例
*/
Texture.cacheAs = function (name, texture) {
this.textureCache[name] = texture;
};
/**
* 清除缓存
*/
Texture.clearCache = function (name) {
if (name != null) {
var texture = this.textureCache[name];
if (texture) {
texture.clearCacheGridSources();
}
delete this.textureCache[name];
}
else {
this.textureCache = {};
}
};
Texture.prototype.onReady = function (callback) {
if (this.ready) {
callback({ width: this.width, height: this.height });
}
else {
this._readyCallbacks.push(callback);
}
};
Texture.prototype.createGridSource = function (w, h, sx, sy, sw, sh, grid) {
w = Math.ceil(w);
h = Math.ceil(h);
var cacheKey = [w, h, sx, sy, sw, sh, grid].join(':');
if (this._gridSourceCache[cacheKey]) {
return this._gridSourceCache[cacheKey].canvas;
}
var top = grid[0], right = grid[1], bottom = grid[2], left = grid[3], repeat = grid[4];
var grids = [
{ x: 0, y: 0, w: left, h: top, sx: sx, sy: sy, sw: left, sh: top },
{ x: w - right, y: 0, w: right, h: top, sx: sx + sw - right, sy: sy, sw: right, sh: top },
{ x: 0, y: h - bottom, w: left, h: bottom, sx: sx, sy: sy + sh - bottom, sw: left, sh: bottom },
{ x: w - right, y: h - bottom, w: right, h: bottom, sx: sx + sw - right, sy: sh - bottom + sy, sw: right, sh: bottom },
{ x: left, y: 0, w: w - left - right, h: top, sx: sx + left, sy: sy, sw: sw - left - right, sh: top },
{ x: left, y: h - bottom, w: w - left - right, h: bottom, sx: sx + left, sy: sh - bottom + sy, sw: sw - left - right, sh: bottom },
{ x: 0, y: top, w: left, h: h - top - bottom, sx: sx, sy: top, sw: left, sh: sh - top - bottom },
{ x: w - right, y: top, w: right, h: h - top - bottom, sx: sx + sw - right, sy: top, sw: right, sh: sh - top - bottom },
];
var centerGrid = { x: left, y: top, w: w - left - right, h: h - top - bottom, sx: sx + left, sy: top, sw: sw - left - right, sh: sh - top - bottom };
var source = CanvasSource.create();
var canvas = source.canvas;
var context = source.context;
source.setSize(w, h);
for (var i = 0, l = grids.length; i < l; i++) {
var g = grids[i];
if (g.w && g.h) {
context.drawImage(this.source, g.sx, g.sy, g.sw, g.sh, Math.ceil(g.x), Math.ceil(g.y), Math.ceil(g.w), Math.ceil(g.h));
}
}
if (repeat) {
var cvs_1 = getRepeatPatternSource(this.source, {
x: centerGrid.sx,
y: centerGrid.sy,
width: centerGrid.sw,
height: centerGrid.sh,
}, centerGrid.sw, centerGrid.sh);
var pattern = context.createPattern(cvs_1, "repeat");
context.fillStyle = pattern;
context.fillRect(Math.ceil(centerGrid.x), Math.ceil(centerGrid.y), Math.ceil(centerGrid.w), Math.ceil(centerGrid.h));
}
else if (centerGrid.w && centerGrid.h) {
context.drawImage(this.source, centerGrid.sx, centerGrid.sy, centerGrid.sw, centerGrid.sh, Math.ceil(centerGrid.x), Math.ceil(centerGrid.y), Math.ceil(centerGrid.w), Math.ceil(centerGrid.h));
}
this._gridSourceCache[cacheKey] = source;
this._gridSourceCount += 1;
return canvas;
};
Texture.prototype.clearCacheGridSources = function () {
for (var k in this._gridSourceCache) {
this._gridSourceCache[k].recycle();
}
this._gridSourceCache = {};
this._gridSourceCount = 0;
};
Texture.prototype.destroy = function () {
if (this.canvasSource) {
this.canvasSource.recycle();
}
this.clearCacheGridSources();
this._readyCallbacks.length = 0;
this.source = this.canvasSource = null;
};
Texture.prototype._createByPath = function (path, sourceRect, textureRect, retryTimes) {
var _this = this;
if (Texture.loadedImages[path]) {
return this._onImageLoaded(img, path, sourceRect, textureRect);
}
var img = Texture.loadingImages[path] || new Image();
var onLoad = function () {
_this._onImageLoaded(img, path, sourceRect, textureRect);
img.removeEventListener("load", onLoad);
img.removeEventListener("error", onError);
};
var onError = function () {
img.removeEventListener("load", onLoad);
img.removeEventListener("error", onError);
delete Texture.loadingImages[path];
img = null;
if (retryTimes) {
_this._createByPath(path, sourceRect, textureRect, --retryTimes);
}
else {
_this._readyCallbacks.length = 0;
if (_this.name != null) {
delete Texture.textureCache[_this.name];
}
}
console.warn("canvas2d: Texture creating fail, error loading source \"" + path + "\".");
};
img.addEventListener('load', onLoad);
img.addEventListener('error', onError);
var src = Texture.version != null ? path + '?v=' + Texture.version : path;
if (!Texture.loadingImages[path]) {
img.crossOrigin = 'anonymous';
Texture.loadingImages[path] = img;
img.src = src;
}
};
Texture.prototype._onImageLoaded = function (img, path, sourceRect, textureRect) {
this._createByImage(img, sourceRect, textureRect);
Texture.loadedImages[path] = img;
delete Texture.loadingImages[path];
if (this._readyCallbacks.length) {
var size = { width: this.width, height: this.height };
for (var i = 0, callback = void 0; callback = this._readyCallbacks[i]; i++) {
callback(size);
}
this._readyCallbacks.length = 0;
}
img = null;
};
Texture.prototype._createByImage = function (image, sourceRect, textureRect) {
var source;
if (!sourceRect && !textureRect) {
source = image;
}
else {
if (!sourceRect) {
sourceRect = {
x: 0,
y: 0,
width: image.width,
height: image.height
};
}
if (!textureRect) {
textureRect = {
x: 0,
y: 0,
width: sourceRect.width,
height: sourceRect.height,
};
}
// source = createCanvas(image, sourceRect, textureRect);
var canvasSource = this.canvasSource = CanvasSource.create();
canvasSource.setSize(textureRect.width, textureRect.height);
canvasSource.context.drawImage(image, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height, textureRect.x, textureRect.y, sourceRect.width, sourceRect.height);
source = canvasSource.canvas;
}
this.width = source.width;
this.height = source.height;
this.source = source;
this.ready = true;
};
return Texture;
}());
Texture.textureCache = {};
Texture.loadingImages = {};
Texture.loadedImages = {};
Texture.retryTimes = 2;
function getCacheKey(source, sourceRect, textureRect) {
var isStr = typeof source === 'string';
if (!isStr && !source.src) {
return null;
}
var src = isStr ? source : source.src;
var sourceRectStr = sourceRect ? [sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height].join(',') : '';
var textureRectStr = textureRect ? [textureRect.x, textureRect.y, textureRect.width, textureRect.height].join(',') : '';
return src + sourceRectStr + textureRectStr;
}
// function createCanvas(image: any, sourceRect: Rect, textureRect: Rect): HTMLCanvasElement {
// var canvas: HTMLCanvasElement = document.createElement("canvas");
// var context: CanvasRenderingContext2D = canvas.getContext('2d');
// canvas.width = textureRect.width;
// canvas.height = textureRect.height;
// context.drawImage(
// image, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height,
// textureRect.x, textureRect.y, sourceRect.width, sourceRect.height);
// return canvas;
// }
var cvs;
var ctx;
function getRepeatPatternSource(source, sourceRect, canvasWidth, canvasHeight) {
if (!cvs) {
cvs = document.createElement("canvas");
ctx = cvs.getContext("2d");
}
cvs.width = canvasWidth;
cvs.height = canvasHeight;
ctx.drawImage(source, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height, 0, 0, sourceRect.width, sourceRect.height);
return cvs;
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
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]; };
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
function __values(o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
function __asyncValues(o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator];
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
}
var BaseAction = (function () {
function BaseAction() {
this.immediate = false;
this.done = false;
}
return BaseAction;
}());
var Delay = (function (_super) {
__extends(Delay, _super);
function Delay(duration) {
var _this = _super.call(this) || this;
_this.elapsed = 0;
_this.duration = duration;
return _this;
}
Delay.prototype.step = function (deltaTime) {
this.elapsed += deltaTime;
if (this.elapsed >= this.duration) {
this.done = true;
}
};
Delay.prototype.end = function () {
};
Delay.prototype.reset = function () {
this.elapsed = 0;
this.done = false;
};
Delay.prototype.reverse = function () {
this.done = false;
this.elapsed = 0;
};
Delay.prototype.destroy = function () {
};
return Delay;
}(BaseAction));
var Callback = (function (_super) {
__extends(Callback, _super);
function Callback(func) {
var _this = _super.call(this) || this;
_this.immediate = true;
_this.func = func;
return _this;
}
Callback.prototype.step = function () {
this.func.call(null);
this.end();
};
Callback.prototype.end = function () {
this.func = null;
this.done = true;
};
Callback.prototype.reset = function () {
this.done = false;
};
Callback.prototype.reverse = function () {
this.done = false;
};
Callback.prototype.destroy = function () {
this.func = null;
};
return Callback;
}(BaseAction));
var Animation = (function (_super) {
__extends(Animation, _super);
function Animation(frameList, frameRate, repetitions) {
var _this = _super.call(this) || this;
_this.elapsed = 0;
_this.count = 0;
_this.frameIndex = 0;
_this.frameList = frameList;
_this.repetitions = repetitions;
_this.interval = 1 / frameRate;
return _this;
}
Animation.prototype.step = function (deltaTime, target) {
this.elapsed += deltaTime;
if (this.elapsed >= this.interval) {
target.texture = this.frameList[this.frameIndex++];
if (this.frameIndex === this.frameList.length) {
if (this.repetitions == null || ++this.count < this.repetitions) {
this.frameIndex = 0;
}
else {
this.end();
}
}
this.elapsed = 0;
}
};
Animation.prototype.end = function () {
this.done = true;
};
Animation.prototype.reset = function () {
this.done = false;
this.frameIndex = 0;
this.elapsed = 0;
this.count = 0;
};
Animation.prototype.reverse = function () {
this.done = false;
this.frameIndex = 0;
this.elapsed = 0;
this.count = 0;
this.frameList = this.frameList.slice().reverse();
};
Animation.prototype.destroy = function () {
this.frameList = null;
};
return Animation;
}(BaseAction));
var Key = 'canvas2d.uid';
var counter = 0;
var cachedColor = {};
function uid(target) {
if (typeof target[Key] === 'undefined') {
Object.defineProperty(target, Key, { value: counter++ });
}
return target[Key];
}
function addArrayItem(array, item) {
if (array.indexOf(item) === -1) {
array.push(item);
}
}
function removeArrayItem(array, item) {
var index = array.indexOf(item);
if (index > -1) {
array.splice(index, 1);
}
}
function convertColor(color) {
if (typeof color === 'string') {
return color;
}
if (cachedColor[color]) {
return cachedColor[color];
}
if (typeof color === 'number') {
var result = color.toString(16);
if (result.length < 3) {
while (result.length < 3) {
result = '0' + result;
}
}
else if (result.length > 3 && result.length < 6) {
while (result.length < 6) {
result = '0' + result;
}
}
if (result.length !== 3 && result.length !== 6) {
throw new Error("canvas2d: Invalid hex color \"0x" + result + "\".");
}
result = cachedColor[color] = '#' + result;
return result;
}
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
var ActionListener = (function () {
function ActionListener(actions) {
this._resolved = false;
this._callbacks = {};
this._actions = actions;
}
ActionListener.prototype.all = function (callback) {
if (this._resolved) {
callback();
}
else {
if (!this._callbacks.all) {
this._callbacks.all = [];
}
addArrayItem(this._callbacks.all, callback);
}
return this;
};
ActionListener.prototype.any = function (callback) {
if (this._resolved) {
callback();
}
else {
if (!this._callbacks.any) {
this._callbacks.any = [];
}
addArrayItem(this._callbacks.any, callback);
}
return this;
};
ActionListener.prototype._step = function () {
var allDone = true;
var anyDone = false;
for (var i = 0, action = void 0; action = this._actions[i]; i++) {
if (action.isDone()) {
anyDone = true;
}
else {
allDone = false;
}
}
if (anyDone && this._callbacks.any) {
for (var i = 0, callback = void 0; callback = this._callbacks.any[i]; i++) {
callback();
}
this._callbacks.any = null;
}
if (allDone && this._callbacks.all) {
for (var i = 0, callback = void 0; callback = this._callbacks.all[i]; i++) {
callback();
}
Action.removeListener(this);
this._resolved = true;
}
};
return ActionListener;
}());
var Transition = (function (_super) {
__extends(Transition, _super);
function Transition(options, duration, isTransitionBy) {
var _this = _super.call(this) || this;
_this.elapsed = 0;
_this.options = [];
_this.deltaValue = {};
_this.duration = duration;
_this.isTransitionBy = isTransitionBy;
if (isTransitionBy) {
_this._initAsTransitionBy(options);
}
else {
_this._initAsTransitionTo(options);
}
return _this;
}
Transition.setDefaultEasingFunc = function (func) {
this.defaultEasingFunc = func;
};
Transition.prototype._initAsTransitionTo = function (options) {
for (var name in options) {
var info = options[name];
var easing = void 0;
var dest = void 0;
if (typeof info === 'number') {
dest = info;
}
else {
easing = info.easing;
dest = info.dest;
}
this.options.push({ name: name, dest: dest, easing: easing });
}
};
Transition.prototype._initAsTransitionBy = function (options) {
var deltaValue = this.deltaValue;
for (var name in options) {
var info = options[name];
var easing = void 0;
var dest = void 0;
if (typeof info === 'number') {
deltaValue[name] = info;
}
else {
easing = info.easing;
deltaValue[name] = info.value;
}
this.options.push({ name: name, dest: dest, easing: easing });
}
};
Transition.prototype._initBeginValue = function (target) {
var beginValue = this.beginValue = {};
var deltaValue = this.deltaValue;
if (this.isTransitionBy) {
for (var i = 0, option = void 0; option = this.options[i]; i++) {
beginValue[option.name] = target[option.name];
option.dest = target[option.name] + deltaValue[option.name];
}
}
else {
for (var i = 0, option = void 0; option = this.options[i]; i++) {
beginValue[option.name] = target[option.name];
deltaValue[option.name] = option.dest - target[option.name];
}
}
};
Transition.prototype.step = function (deltaTime, target) {
this.elapsed += deltaTime;
if (this.beginValue == null) {
this._initBeginValue(target);
}
if (this.elapsed >= this.duration) {
return this.end(target);
}
var percent = this.elapsed / this.duration;
var beginValue = this.beginValue;
var deltaValue = this.deltaValue;
for (var i = 0, option = void 0; option = this.options[i]; i++) {
var name = option.name, dest = option.dest, easing = option.easing;
easing = easing || Transition.defaultEasingFunc;
target[name] = beginValue[name] + (easing(percent) * deltaValue[name]);
}
};
Transition.prototype.end = function (target) {
for (var i = 0, option = void 0; option = this.options[i]; i++) {
target[option.name] = option.dest;
}
this.done = true;
};
Transition.prototype.destroy = function () {
this.beginValue = null;
this.deltaValue = null;
this.options = null;
};
Transition.prototype.reset = function () {
this.done = false;
this.elapsed = 0;
};
Transition.prototype.reverse = function () {
this.done = false;
this.elapsed = 0;
var _a = this, options = _a.options, beginValue = _a.beginValue, deltaValue = _a.deltaValue;
for (var i = 0, option = void 0; option = options[i]; i++) {
var dest = beginValue[option.name];
beginValue[option.name] = option.dest;
deltaValue[option.name] = -deltaValue[option.name];
option.dest = dest;
}
};
return Transition;
}(BaseAction));
Transition.defaultEasingFunc = Tween.easeInOutQuad;
(function (ActionType) {
ActionType[ActionType["TO"] = 0] = "TO";
ActionType[ActionType["BY"] = 1] = "BY";
ActionType[ActionType["ANIM"] = 2] = "ANIM";
ActionType[ActionType["WAIT"] = 3] = "WAIT";
ActionType[ActionType["CALLBACK"] = 4] = "CALLBACK";
})(exports.ActionType || (exports.ActionType = {}));
(function (ActionRepeatMode) {
ActionRepeatMode[ActionRepeatMode["NONE"] = 0] = "NONE";
ActionRepeatMode[ActionRepeatMode["REPEAT"] = 1] = "REPEAT";
ActionRepeatMode[ActionRepeatMode["REVERSE_REPEAT"] = 2] = "REVERSE_REPEAT";
})(exports.ActionRepeatMode || (exports.ActionRepeatMode = {}));
var Action = (function () {
function Action(target, tag) {
this._queue = [];
this._currentIndex = 0;
this._done = false;
this._repeatMode = exports.ActionRepeatMode.NONE;
/**
* Action running state
*/
this.isRunning = false;
this.target = target;
this.tag = tag;
}
Object.defineProperty(Action, "scheduleCostTime", {
get: function () {
return this._scheduleCostTime;
},
enumerable: true,
configurable: true
});
/**
* Stop action by target
*/
Action.stop = function (target, tag) {
var list = Action._actionList.slice();
for (var i = 0, action = void 0; action = list[i]; i++) {
if (action.target === target) {
if (tag == null || action.tag == tag) {
action.stop();
}
}
}
};
/**
* Listen a action list, when all actions are done then publish to listener
*/
Action.listen = function (actions) {
var listener = new ActionListener(actions);
Action._listenerList.push(listener);
return listener;
};
Action.removeListener = function (listener) {
removeArrayItem(this._listenerList, this);
};
Action.schedule = function (deltaTime) {
var startTime = Date.now();
var actionList = Action._actionList.slice();
var listenerList = Action._listenerList.slice();
for (var i = 0, action = void 0; action = actionList[i]; i++) {
action._step(deltaTime);
if (action._done) {
removeArrayItem(Action._actionList, action);
}
}
for (var i = 0, listener = void 0; listener = listenerList[i]; i++) {
listener._step();
}
Action._scheduleCostTime = Date.now() - startTime;
};
Action.prototype.isDone = function () {
return this._done;
};
Action.prototype.setRepeatMode = function (mode) {
this._repeatMode = mode;
return this;
};
Object.defineProperty(Action.prototype, "repeatMode", {
get: function () {
return this._repeatMode;
},
set: function (mode) {
this._repeatMode = mode;
},
enumerable: true,
configurable: true
});
Action.prototype.queue = function (actions) {
for (var i = 0, action = void 0; action = actions[i]; i++) {
switch (action.type) {
case exports.ActionType.ANIM:
this.animate(action.frameList, action.frameRate, action.repetitions);
break;
case exports.ActionType.BY:
this.by(action.options, action.duration);
break;
case exports.ActionType.TO:
this.to(action.options, action.duration);
break;
case exports.ActionType.WAIT:
this.wait(action.duration);
break;
case exports.ActionType.CALLBACK:
this.then(action.callback);
break;
}
}
return this;
};
/**
* Add a callback, it will exec after previous action is done.
*/
Action.prototype.then = function (callback) {
this._queue.push(new Callback(callback));
return this;
};
/**
* Add a delay action.
*/
Action.prototype.wait = function (time) {
this._queue.push(new Delay(time));
return this;
};
/**
* Add a animation action
*/
Action.prototype.animate = function (frameList, frameRate, repetitions) {
var anim = new Animation(frameList, frameRate, repetitions);
this._queue.push(anim);
anim.step(anim.interval, this.target);
return this;
};
/**
* TransitionTo action
*/
Action.prototype.to = function (attrs, duration) {
this._queue.push(new Transition(attrs, duration));
return this;
};
/**
* TransitionBy action
*/
Action.prototype.by = function (attrs, duration) {
this._queue.push(new Transition(attrs, duration, true));
return this;
};
/**
* Start the action
*/
Action.prototype.start = function () {
if (!this.isRunning) {
addArrayItem(Action._actionList, this);
this.isRunning = true;
}
return this;
};
/**
* Stop the action
*/
Action.prototype.stop = function () {
for (var i = 0, action = void 0; action = this._queue[i]; i++) {
action.destroy();
}
this._done = true;
this.isRunning = false;
this._queue.length = 0;
removeArrayItem(Action._actionList, this);
};
Action.prototype.clear = function () {
for (var i = 0, action = void 0; action = this._queue[i]; i++) {
action.destroy();
}
this._done = false;
this.isRunning = false;
this._queue.length = 0;
this._currentIndex = 0;
this._repeatMode = exports.ActionRepeatMode.NONE;
removeArrayItem(Action._actionList, this);
};
Action.prototype._step = function (deltaTime) {
if (!this._queue.length || this._currentIndex >= this._queue.length) {
return;
}
var action = this._queue[this._currentIndex];
action.step(deltaTime, this.target);
if (action.done) {
this._currentIndex += 1;
if (this._currentIndex >= this._queue.length) {
this._onAllActionDone();
}
else if (action.immediate) {
this._step(deltaTime);
}
}
};
Action.prototype._onAllActionDone = function () {
switch (this._repeatMode) {
case exports.ActionRepeatMode.REPEAT:
for (var i = 0, action = void 0; action = this._queue[i]; i++) {
action.reset();
}
this._currentIndex = 0;
break;
case exports.ActionRepeatMode.REVERSE_REPEAT:
for (var i = 0, action = void 0; action = this._queue[i]; i++) {
action.reverse();
}
this._currentIndex = 0;
break;
default:
this._done = true;
this.isRunning = false;
this.target = null;
for (var i = 0, action = void 0; action = this._queue[i]; i++) {
action.destroy();
}
this._queue.length = 0;
break;
}
};
return Action;
}());
Action._actionList = [];
Action._listenerList = [];
Action._scheduleCostTime = 0;
var EventEmitter = (function () {
function EventEmitter() {
}
EventEmitter.prototype.addListener = function (type, listener) {
if (typeof listener !== 'function') {
return this;
}
var id = uid(this);
if (!EventEmitter._eventCache[id]) {
EventEmitter._eventCache[id] = {};
}
if (!EventEmitter._eventCache[id][type]) {
EventEmitter._eventCache[id][type] = [];
}
var events = EventEmitter._eventCache[id][type];
for (var i = 0, ev = void 0; ev = events[i]; i++) {
if (ev.listener === listener && !ev.once) {
return this;
}
}
events.push({ listener: listener });
return this;
};
EventEmitter.prototype.on = function (type, listener) {
return this.addListener(type, listener);
};
EventEmitter.prototype.once = function (type, listener) {
if (typeof listener !== 'function') {
return this;
}
var id = uid(this);
if (!EventEmitter._eventCache[id]) {
EventEmitter._eventCache[id] = {};
}
if (!EventEmitter._eventCache[id][type]) {
EventEmitter._eventCache[id][type] = [];
}
var events = EventEmitter._eventCache[id][type];
for (var i = 0, ev = void 0; ev = events[i]; i++) {
if (ev.listener === listener && ev.once) {
return this;
}
}
events.push({ listener: listener, once: true });
return this;
};
EventEmitter.prototype.removeListener = function (type, listener) {
var cache = EventEmitter._eventCache[uid(this)];
if (cache && cache[type]) {
var events = cache[type];
var temp = events.slice();
for (var i = 0, l = temp.length; i < l; i++) {
var ev = temp[i];
if (ev.listener === listener) {
removeArrayItem(events, ev);
}
}
if (!events.length) {
delete cache[type];
}
}
return this;
};
EventEmitter.prototype.removeAllListeners = function (type) {
var id = uid(this);
var cache = EventEmitter._eventCache[id];
if (cache) {
if (type == null) {
EventEmitter._eventCache[id] = null;
}
else {
delete cache[type];
}
}
return this;
};
EventEmitter.prototype.hasListener = function (type) {
var id = uid(this);
var eventCache = EventEmitter._eventCache;
if (!eventCache[id] || !eventCache[id][type] || !eventCache[id][type].length) {
return false;
}
return true;
};
EventEmitter.prototype.emit = function (type) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var id = uid(this);
var cache = EventEmitter._eventCache[id];
if (cache && cache[type]) {
var events = cache[type];
var temp = events.slice();
for (var i = 0, l = temp.length; i < l; i++) {
var ev = temp[i];
if (ev) {
if (typeof ev.listener === 'function') {
ev.listener.apply(this, args);
}
if (ev.once) {
removeArrayItem(events, ev);
}
}
}
}
return this;
};
return EventEmitter;
}());
EventEmitter._eventCache = {};
var instance;
var ReleasePool = (function () {
function ReleasePool() {
this._objs = [];
}
ReleasePool.prototype.add = function (obj) {
var _this = this;
this._objs.push(obj);
if (this._timerId != null) {
return;
}
this._timerId = setTimeout(function () { return _this._release(); }, 0);
};
ReleasePool.prototype._release = function () {
for (var i = 0, obj = void 0; obj = this._objs[i]; i++) {
for (var key in obj) {
delete obj[key];
}
}
this._timerId = null;
this._objs.length = 0;
};
Object.defineProperty(ReleasePool, "instance", {
get: function () {
if (!instance) {
instance = new ReleasePool();
}
return instance;
},
enumerable: true,
configurable: true
});
return ReleasePool;
}());
// import { CanvasFrameBuffer } from '../framebuffer/CanvasFrameBuffer';
var RAD_PER_DEG = Math.PI / 180;
(function (AlignType) {
AlignType[AlignType["TOP"] = 0] = "TOP";
AlignType[AlignType["RIGHT"] = 1] = "RIGHT";
AlignType[AlignType["BOTTOM"] = 2] = "BOTTOM";
AlignType[AlignType["LEFT"] = 3] = "LEFT";
AlignType[AlignType["CENTER"] = 4] = "CENTER";
})(exports.AlignType || (exports.AlignType = {}));
(function (BlendMode) {
BlendMode[BlendMode["SOURCE_IN"] = 0] = "SOURCE_IN";
BlendMode[BlendMode["SOURCE_OVER"] = 1] = "SOURCE_OVER";
BlendMode[BlendMode["SOURCE_ATOP"] = 2] = "SOURCE_ATOP";
BlendMode[BlendMode["SOURCE_OUT"] = 3] = "SOURCE_OUT";
BlendMode[BlendMode["DESTINATION_OVER"] = 4] = "DESTINATION_OVER";
BlendMode[BlendMode["DESTINATION_IN"] = 5] = "DESTINATION_IN";
BlendMode[BlendMode["DESTINATION_OUT"] = 6] = "DESTINATION_OUT";
BlendMode[BlendMode["DESTINATION_ATOP"] = 7] = "DESTINATION_ATOP";
BlendMode[BlendMode["LIGHTER"] = 8] = "LIGHTER";
BlendMode[BlendMode["COPY"] = 9] = "COPY";
BlendMode[BlendMode["XOR"] = 10] = "XOR";
})(exports.BlendMode || (exports.BlendMode = {}));
var BlendModeStrings = (_a = {},
_a[exports.BlendMode.SOURCE_IN] = "source-in",
_a[exports.BlendMode.SOURCE_OVER] = "source-over",
_a[exports.BlendMode.SOURCE_ATOP] = "source-atop",
_a[exports.BlendMode.SOURCE_OUT] = "source-out",
_a[exports.BlendMode.DESTINATION_OVER] = "destination-over",
_a[exports.BlendMode.DESTINATION_IN] = "destination-in",
_a[exports.BlendMode.DESTINATION_OUT] = "destination-out",
_a[exports.BlendMode.DESTINATION_ATOP] = "destination-atop",
_a[exports.BlendMode.LIGHTER] = "lighter",
_a[exports.BlendMode.COPY] = "copy",
_a[exports.BlendMode.XOR] = "xor",
_a);
var Sprite = (function (_super) {
__extends(Sprite, _super);
function Sprite(props) {
var _this = _super.call(this) || this;
_this._width = 0;
_this._height = 0;
_this._originX = 0.5;
_this._originY = 0.5;
_this._rotation = 0;
_this._rotationInRadians = 0;
_this._originPixelX = 0;
_this._originPixelY = 0;
_this.x = 0;
_this.y = 0;
_this.scaleX = 1;
_this.scaleY = 1;
_this.radius = 0;
_this.opacity = 1;
_this.sourceX = 0;
_this.sourceY = 0;
_this.autoResize = true;
_this.flippedX = false;
_this.flippedY = false;
_this.visible = true;
_this.clipOverflow = false;
_this.touchEnabled = true;
_this.mouseEnabled = true;
_this.id = uid(_this);
// this._canvasFrameBuffer = CanvasFrameBuffer.create(this.