mirror of
https://github.com/konvajs/konva.git
synced 2025-09-19 19:07:59 +08:00

Many sprite animation tools pack the sprites in such a way that the size of the image is optimized. In order to play the sprite properly you need to change the x and y coordinate of the image so the sprite plays properly. Currently in Kineticjs there is no place to store this offset data. I added the offset data optionally to the sprite object and changed the scene function to use it if it exists.
333 lines
9.3 KiB
JavaScript
333 lines
9.3 KiB
JavaScript
(function() {
|
|
/**
|
|
* Sprite constructor
|
|
* @constructor
|
|
* @memberof Kinetic
|
|
* @augments Kinetic.Shape
|
|
* @param {Object} config
|
|
* @param {String} config.animation animation key
|
|
* @param {Object} config.animations animation map
|
|
* @param {Integer} [config.frameIndex] animation frame index
|
|
* @param {Image} config.image image object
|
|
* @@shapeParams
|
|
* @@nodeParams
|
|
* @example
|
|
* var imageObj = new Image();
|
|
* imageObj.onload = function() {
|
|
* var sprite = new Kinetic.Sprite({
|
|
* x: 200,
|
|
* y: 100,
|
|
* image: imageObj,
|
|
* animation: 'standing',
|
|
* animations: {
|
|
* standing: [
|
|
* // x, y, width, height (6 frames)
|
|
* 0, 0, 49, 109,
|
|
* 52, 0, 49, 109,
|
|
* 105, 0, 49, 109,
|
|
* 158, 0, 49, 109,
|
|
* 210, 0, 49, 109,
|
|
* 262, 0, 49, 109
|
|
* ],
|
|
* kicking: [
|
|
* // x, y, width, height (6 frames)
|
|
* 0, 109, 45, 98,
|
|
* 45, 109, 45, 98,
|
|
* 95, 109, 63, 98,
|
|
* 156, 109, 70, 98,
|
|
* 229, 109, 60, 98,
|
|
* 287, 109, 41, 98
|
|
* ]
|
|
* },
|
|
* frameRate: 7,
|
|
* frameIndex: 0
|
|
* });
|
|
* };
|
|
* imageObj.src = '/path/to/image.jpg'
|
|
*/
|
|
Kinetic.Sprite = function(config) {
|
|
this.___init(config);
|
|
};
|
|
|
|
Kinetic.Sprite.prototype = {
|
|
___init: function(config) {
|
|
// call super constructor
|
|
Kinetic.Shape.call(this, config);
|
|
this.className = 'Sprite';
|
|
|
|
this._updated = true;
|
|
var that = this;
|
|
this.anim = new Kinetic.Animation(function() {
|
|
// if we don't need to redraw layer we should return false
|
|
var updated = that._updated;
|
|
that._updated = false;
|
|
return updated;
|
|
});
|
|
this.on('animationChange.kinetic', function() {
|
|
// reset index when animation changes
|
|
this.frameIndex(0);
|
|
});
|
|
this.on('frameIndexChange.kinetic', function() {
|
|
this._updated = true;
|
|
});
|
|
// smooth change for frameRate
|
|
this.on('frameRateChange.kinetic', function() {
|
|
if (!this.anim.isRunning()) {
|
|
return;
|
|
}
|
|
clearInterval(this.interval);
|
|
this._setInterval();
|
|
});
|
|
|
|
this.sceneFunc(this._sceneFunc);
|
|
this.hitFunc(this._hitFunc);
|
|
},
|
|
_sceneFunc: function(context) {
|
|
var anim = this.getAnimation(),
|
|
index = this.frameIndex(),
|
|
ix4 = index * 4,
|
|
set = this.getAnimations()[anim],
|
|
offsets = this.getOffsets(),
|
|
x = set[ix4 + 0],
|
|
y = set[ix4 + 1],
|
|
width = set[ix4 + 2],
|
|
height = set[ix4 + 3],
|
|
image = this.getImage();
|
|
|
|
if(image) {
|
|
if (offsets) {
|
|
var offset = offsets[anim],
|
|
ix2 = index * 2;
|
|
context.drawImage(image, x, y, width, height, offset[ix2 + 0], offset[ix2 + 1], width, height);
|
|
} else {
|
|
context.drawImage(image, x, y, width, height, 0, 0, width, height);
|
|
}
|
|
}
|
|
},
|
|
_hitFunc: function(context) {
|
|
var anim = this.getAnimation(),
|
|
index = this.frameIndex(),
|
|
ix4 = index * 4,
|
|
set = this.getAnimations()[anim],
|
|
width = set[ix4 + 2],
|
|
height = set[ix4 + 3];
|
|
|
|
context.beginPath();
|
|
context.rect(0, 0, width, height);
|
|
context.closePath();
|
|
context.fillShape(this);
|
|
},
|
|
_useBufferCanvas: function() {
|
|
return (this.hasShadow() || this.getAbsoluteOpacity() !== 1) && this.hasStroke();
|
|
},
|
|
_setInterval: function() {
|
|
var that = this;
|
|
this.interval = setInterval(function() {
|
|
that._updateIndex();
|
|
}, 1000 / this.getFrameRate());
|
|
},
|
|
/**
|
|
* start sprite animation
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
*/
|
|
start: function() {
|
|
var layer = this.getLayer();
|
|
|
|
/*
|
|
* animation object has no executable function because
|
|
* the updates are done with a fixed FPS with the setInterval
|
|
* below. The anim object only needs the layer reference for
|
|
* redraw
|
|
*/
|
|
this.anim.setLayers(layer);
|
|
this._setInterval();
|
|
this.anim.start();
|
|
},
|
|
/**
|
|
* stop sprite animation
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
*/
|
|
stop: function() {
|
|
this.anim.stop();
|
|
clearInterval(this.interval);
|
|
},
|
|
/**
|
|
* determine if animation of sprite is running or not. returns true or false
|
|
* @method
|
|
* @memberof Kinetic.Animation.prototype
|
|
* @returns {Boolean}
|
|
*/
|
|
isRunning: function() {
|
|
return this.anim.isRunning();
|
|
},
|
|
_updateIndex: function() {
|
|
var index = this.frameIndex(),
|
|
animation = this.getAnimation(),
|
|
animations = this.getAnimations(),
|
|
anim = animations[animation],
|
|
len = anim.length / 4;
|
|
|
|
if(index < len - 1) {
|
|
this.frameIndex(index + 1);
|
|
}
|
|
else {
|
|
this.frameIndex(0);
|
|
}
|
|
}
|
|
};
|
|
Kinetic.Util.extend(Kinetic.Sprite, Kinetic.Shape);
|
|
|
|
// add getters setters
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Sprite, 'animation');
|
|
|
|
/**
|
|
* get/set animation key
|
|
* @name animation
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
* @param {String} anim animation key
|
|
* @returns {String}
|
|
* @example
|
|
* // get animation key
|
|
* var animation = sprite.animation();
|
|
*
|
|
* // set animation key
|
|
* sprite.animation('kicking');
|
|
*/
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Sprite, 'animations');
|
|
|
|
/**
|
|
* get/set animations map
|
|
* @name animations
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
* @param {Object} animations
|
|
* @returns {Object}
|
|
* @example
|
|
* // get animations map
|
|
* var animations = sprite.animations();
|
|
*
|
|
* // set animations map
|
|
* sprite.animations({
|
|
* standing: [
|
|
* // x, y, width, height (6 frames)
|
|
* 0, 0, 49, 109,
|
|
* 52, 0, 49, 109,
|
|
* 105, 0, 49, 109,
|
|
* 158, 0, 49, 109,
|
|
* 210, 0, 49, 109,
|
|
* 262, 0, 49, 109
|
|
* ],
|
|
* kicking: [
|
|
* // x, y, width, height (6 frames)
|
|
* 0, 109, 45, 98,
|
|
* 45, 109, 45, 98,
|
|
* 95, 109, 63, 98,
|
|
* 156, 109, 70, 98,
|
|
* 229, 109, 60, 98,
|
|
* 287, 109, 41, 98
|
|
* ]
|
|
* });
|
|
*/
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Sprite, 'offsets');
|
|
|
|
/**
|
|
* get/set offsets map
|
|
* @name offsets
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
* @param {Object} offsets
|
|
* @returns {Object}
|
|
* @example
|
|
* // get offsets map
|
|
* var offsets = sprite.offsets();
|
|
*
|
|
* // set offsets map
|
|
* sprite.offsets({
|
|
* standing: [
|
|
* // x, y (6 frames)
|
|
* 0, 0,
|
|
* 0, 0,
|
|
* 5, 0,
|
|
* 0, 0,
|
|
* 0, 3,
|
|
* 2, 0
|
|
* ],
|
|
* kicking: [
|
|
* // x, y (6 frames)
|
|
* 0, 5,
|
|
* 5, 0,
|
|
* 10, 0,
|
|
* 0, 0,
|
|
* 2, 1,
|
|
* 0, 0
|
|
* ]
|
|
* });
|
|
*/
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Sprite, 'image');
|
|
|
|
/**
|
|
* get/set image
|
|
* @name image
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
* @param {Image} image
|
|
* @returns {Image}
|
|
* @example
|
|
* // get image
|
|
* var image = sprite.image();
|
|
*
|
|
* // set image
|
|
* sprite.image(imageObj);
|
|
*/
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Sprite, 'frameIndex', 0);
|
|
|
|
/**
|
|
* set/set animation frame index
|
|
* @name frameIndex
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
* @param {Integer} frameIndex
|
|
* @returns {Integer}
|
|
* @example
|
|
* // get animation frame index
|
|
* var frameIndex = sprite.frameIndex();
|
|
*
|
|
* // set animation frame index
|
|
* sprite.frameIndex(3);
|
|
*/
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Sprite, 'frameRate', 17);
|
|
|
|
/**
|
|
* get/set frame rate in frames per second. Increase this number to make the sprite
|
|
* animation run faster, and decrease the number to make the sprite animation run slower
|
|
* The default is 17 frames per second
|
|
* @name frameRate
|
|
* @method
|
|
* @memberof Kinetic.Sprite.prototype
|
|
* @param {Integer} frameRate
|
|
* @returns {Integer}
|
|
* @example
|
|
* // get frame rate
|
|
* var frameRate = sprite.frameRate();
|
|
*
|
|
* // set frame rate to 2 frames per second
|
|
* sprite.frameRate(2);
|
|
*/
|
|
|
|
Kinetic.Factory.backCompat(Kinetic.Sprite, {
|
|
index: 'frameIndex',
|
|
getIndex: 'getFrameIndex',
|
|
setIndex: 'setFrameIndex'
|
|
});
|
|
|
|
Kinetic.Collection.mapMethods(Kinetic.Sprite);
|
|
})();
|