Hilo/docs/api-zh/code/util/TextureAtlas.js
2017-12-11 14:05:40 +08:00

224 lines
7.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Hilo
* Copyright 2015 alibaba.com
* Licensed under the MIT License
*/
/**
* @class TextureAtlas纹理集是将许多小的纹理图片整合到一起的一张大图。这个类可根据一个纹理集数据读取纹理小图、精灵动画等。
* @param {Object} atlasData 纹理集数据。它可包含如下数据:
* <ul>
* <li><b>image</b> - 纹理集图片。必需。</li>
* <li><b>width</b> - 纹理集图片宽度。若frames数据为Object时此属性必需。</li>
* <li><b>height</b> - 纹理集图片高度。若frames数据为Object时此属性必需。</li>
* <li><b>frames</b> - 纹理集帧数据可以是Array或Object。必需。
* <ul>
* <li>若为Array则每项均为一个纹理图片帧数据[[0, 0, 50, 50], [0, 50, 50, 50]。</li>
* <li>若为Object则需包含frameWidth(帧宽)、frameHeight(帧高)、numFrames(帧数) 属性。</li>
* </ul>
* </li>
* <li><b>sprites</b> - 纹理集精灵动画定义其每个值均定义一个精灵。为Object对象。可选。
* <ul>
* <li>若为Number即此精灵只包含一帧此帧为帧数据中索引为当前值的帧。如sprites:{'foo':1}。</li>
* <li>若为Array则每项均为一个帧的索引值。如sprites:{'foo':[0, 1, 2, 3]}。</li>
* <li>若为Object则需包含from(起始帧索引值)、to(末帧索引值) 属性。</li>
* </ul>
* </li>
* </ul>
* @module hilo/util/TextureAtlas
* @requires hilo/core/Class
*/
var TextureAtlas = (function(){
return Class.create(/** @lends TextureAtlas.prototype */{
constructor: function(atlasData){
this._frames = parseTextureFrames(atlasData);
this._sprites = parseTextureSprites(atlasData, this._frames);
},
_frames: null,
_sprites: null,
/**
* 获取指定索引位置index的帧数据。
* @param {Int} index 要获取帧的索引位置。
* @returns {Object} 帧数据。
*/
getFrame: function(index){
var frames = this._frames;
return frames && frames[index];
},
/**
* 获取指定id的精灵数据。
* @param {String} id 要获取精灵的id。
* @returns {Object} 精灵数据。
*/
getSprite: function(id){
var sprites = this._sprites;
return sprites && sprites[id];
},
Statics: /** @lends TextureAtlas */ {
/**
* 创建精灵帧数据的快捷方法。
* @param {String|Array} name 动画名称|一组动画数据
* @param {String} frames 帧数据 eg:"0-5"代表第0到第5帧
* @param {Number} w 每帧的宽
* @param {Number} h 每帧的高
* @param {Boolean} loop 是否循环
* @param {Number} duration 每帧间隔 默认单位帧, 如果sprite的timeBased为true则单位是毫秒默认一帧
* @example
* //方式一 单个动画
* createSpriteFrames("walk", "0-5,8,9", meImg, 55, 88, true, 1);
* //方式二 多组动画
* createSpriteFrames([
* ["walk", "0-5,8,9", meImg, 55, 88, true, 1],
* ["jump", "0-5", meImg, 55, 88, false, 1]
* ]);
*/
createSpriteFrames:function(name, frames, img, w, h, loop, duration){
var i, l;
if(Object.prototype.toString.call(name) === "[object Array]"){
var res = [];
for(i = 0, l = name.length;i < l;i ++){
res = res.concat(this.createSpriteFrames.apply(this, name[i]));
}
return res;
}
else{
if(typeof(frames) === "string"){
var all = frames.split(",");
frames = [];
for(var j = 0, jl = all.length;j < jl;j ++){
var temp = all[j].split("-");
if(temp.length == 1){
frames.push(parseInt(temp[0]));
}
else{
for(i = parseInt(temp[0]), l = parseInt(temp[1]);i <= l;i ++){
frames.push(i);
}
}
}
}
var col = Math.floor(img.width/w);
for(i = 0;i < frames.length;i ++){
var n = frames[i];
frames[i] = {
rect:[w*(n%col), h*Math.floor(n/col), w, h],
image:img,
duration:duration
};
}
frames[0].name = name;
if(loop){
frames[frames.length-1].next = name;
}
else{
frames[frames.length-1].stop = true;
}
return frames;
}
}
}
});
/**
* 解析纹理集帧数据。
* @private
*/
function parseTextureFrames(atlasData){
var i, len;
var frameData = atlasData.frames;
if(!frameData) return null;
var frames = [], obj;
if(frameData instanceof Array){ //frames by array
for(i = 0, len = frameData.length; i < len; i++){
obj = frameData[i];
frames[i] = {
image: atlasData.image,
rect: obj
};
}
}else{ //frames by object
var frameWidth = frameData.frameWidth;
var frameHeight = frameData.frameHeight;
var cols = atlasData.width / frameWidth | 0;
var rows = atlasData.height / frameHeight | 0;
var numFrames = frameData.numFrames || cols * rows;
for(i = 0; i < numFrames; i++){
frames[i] = {
image: atlasData.image,
rect: [i%cols*frameWidth, (i/cols|0)*frameHeight, frameWidth, frameHeight]
};
}
}
return frames;
}
/**
* 解析精灵数据。
* @private
*/
function parseTextureSprites(atlasData, frames){
var i, len;
var spriteData = atlasData.sprites;
if(!spriteData) return null;
var sprites = {}, sprite, spriteFrames, spriteFrame;
for(var s in spriteData){
sprite = spriteData[s];
if(isNumber(sprite)){ //single frame
spriteFrames = translateSpriteFrame(frames[sprite]);
}else if(sprite instanceof Array){ //frames by array
spriteFrames = [];
for(i = 0, len = sprite.length; i < len; i++){
var spriteObj = sprite[i], frameObj;
if(isNumber(spriteObj)){
spriteFrame = translateSpriteFrame(frames[spriteObj]);
}else{
frameObj = spriteObj.rect;
if(isNumber(frameObj)) frameObj = frames[spriteObj.rect];
spriteFrame = translateSpriteFrame(frameObj, spriteObj);
}
spriteFrames[i] = spriteFrame;
}
}else{ //frames by object
spriteFrames = [];
for(i = sprite.from; i <= sprite.to; i++){
spriteFrames[i - sprite.from] = translateSpriteFrame(frames[i], sprite[i]);
}
}
sprites[s] = spriteFrames;
}
return sprites;
}
function translateSpriteFrame(frameObj, spriteObj){
var spriteFrame = {
image: frameObj.image,
rect: frameObj.rect
};
if(spriteObj){
spriteFrame.name = spriteObj.name || null;
spriteFrame.duration = spriteObj.duration || 0;
spriteFrame.stop = !!spriteObj.stop;
spriteFrame.next = spriteObj.next || null;
}
return spriteFrame;
}
function isNumber(value){
return typeof value === 'number';
}
})();