2012-03-07 13:45:48 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Image
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
2012-07-09 12:56:52 +08:00
|
|
|
/**
|
|
|
|
* Image constructor
|
|
|
|
* @constructor
|
|
|
|
* @augments Kinetic.Shape
|
|
|
|
* @param {Object} config
|
2012-07-17 15:32:26 +08:00
|
|
|
* @param {ImageObject} config.image
|
2012-07-15 07:25:56 +08:00
|
|
|
* @param {Number} [config.width]
|
|
|
|
* @param {Number} [config.height]
|
|
|
|
* @param {Object} [config.crop]
|
2012-07-09 12:56:52 +08:00
|
|
|
*/
|
2012-08-23 14:35:21 +08:00
|
|
|
Kinetic.Image = function(config) {
|
|
|
|
this._initImage(config);
|
|
|
|
};
|
|
|
|
|
|
|
|
Kinetic.Image.prototype = {
|
|
|
|
_initImage: function(config) {
|
2012-07-04 03:07:27 +08:00
|
|
|
this.shapeType = "Image";
|
2012-11-15 13:55:16 +08:00
|
|
|
|
2012-07-29 01:46:16 +08:00
|
|
|
// call super constructor
|
2012-08-23 14:35:21 +08:00
|
|
|
Kinetic.Shape.call(this, config);
|
2012-11-19 12:28:55 +08:00
|
|
|
this._setDrawFuncs();
|
2012-08-16 14:13:50 +08:00
|
|
|
|
|
|
|
var that = this;
|
|
|
|
this.on('imageChange', function(evt) {
|
|
|
|
that._syncSize();
|
|
|
|
});
|
|
|
|
|
|
|
|
this._syncSize();
|
2012-07-29 01:46:16 +08:00
|
|
|
},
|
|
|
|
drawFunc: function(context) {
|
2012-11-13 11:59:19 +08:00
|
|
|
var width = this.getWidth(), height = this.getHeight();
|
2012-06-25 03:44:08 +08:00
|
|
|
|
2012-08-15 14:52:53 +08:00
|
|
|
context.beginPath();
|
|
|
|
context.rect(0, 0, width, height);
|
|
|
|
context.closePath();
|
2012-11-24 06:54:32 +08:00
|
|
|
this.fillStroke(context);
|
2012-08-16 14:13:50 +08:00
|
|
|
|
2012-08-15 14:52:53 +08:00
|
|
|
if(this.attrs.image) {
|
2012-07-29 01:46:16 +08:00
|
|
|
// if cropping
|
|
|
|
if(this.attrs.crop && this.attrs.crop.width && this.attrs.crop.height) {
|
|
|
|
var cropX = this.attrs.crop.x ? this.attrs.crop.x : 0;
|
|
|
|
var cropY = this.attrs.crop.y ? this.attrs.crop.y : 0;
|
|
|
|
var cropWidth = this.attrs.crop.width;
|
|
|
|
var cropHeight = this.attrs.crop.height;
|
|
|
|
this.drawImage(context, this.attrs.image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height);
|
2012-04-28 10:08:45 +08:00
|
|
|
}
|
2012-07-29 01:46:16 +08:00
|
|
|
// no cropping
|
|
|
|
else {
|
|
|
|
this.drawImage(context, this.attrs.image, 0, 0, width, height);
|
|
|
|
}
|
|
|
|
}
|
2012-07-04 03:07:27 +08:00
|
|
|
},
|
2012-11-19 11:50:50 +08:00
|
|
|
drawHitFunc: function(context) {
|
2012-11-21 15:03:24 +08:00
|
|
|
var width = this.getWidth(), height = this.getHeight(), imageBuffer = this.imageBuffer, appliedShadow = false;
|
2012-11-13 11:59:19 +08:00
|
|
|
|
|
|
|
context.beginPath();
|
|
|
|
context.rect(0, 0, width, height);
|
|
|
|
context.closePath();
|
2012-11-24 06:54:32 +08:00
|
|
|
this.fillStroke(context);
|
2012-11-19 11:50:50 +08:00
|
|
|
|
|
|
|
if(imageBuffer) {
|
2012-11-19 12:28:55 +08:00
|
|
|
this.drawImage(context, this.imageBuffer, 0, 0, width, height);
|
2012-11-19 11:50:50 +08:00
|
|
|
}
|
2012-11-13 11:59:19 +08:00
|
|
|
},
|
2012-07-17 15:32:26 +08:00
|
|
|
/**
|
|
|
|
* apply filter
|
|
|
|
* @name applyFilter
|
|
|
|
* @methodOf Kinetic.Image.prototype
|
|
|
|
* @param {Object} config
|
2012-11-16 13:51:33 +08:00
|
|
|
* @param {Function} filter filter function
|
2012-11-19 11:50:50 +08:00
|
|
|
* @param {Object} [config] optional config object used to configure filter
|
2012-11-16 13:51:33 +08:00
|
|
|
* @param {Function} [callback] callback function to be called once
|
2012-07-17 15:32:26 +08:00
|
|
|
* filter has been applied
|
|
|
|
*/
|
2012-11-16 13:51:33 +08:00
|
|
|
applyFilter: function(filter, config, callback) {
|
2012-09-25 11:34:23 +08:00
|
|
|
var canvas = new Kinetic.Canvas(this.attrs.image.width, this.attrs.image.height);
|
2012-08-20 04:09:27 +08:00
|
|
|
var context = canvas.getContext();
|
|
|
|
context.drawImage(this.attrs.image, 0, 0);
|
2012-09-25 11:34:23 +08:00
|
|
|
try {
|
|
|
|
var imageData = context.getImageData(0, 0, canvas.getWidth(), canvas.getHeight());
|
2012-11-16 13:51:33 +08:00
|
|
|
filter(imageData, config);
|
2012-07-17 15:32:26 +08:00
|
|
|
var that = this;
|
2012-08-20 04:09:27 +08:00
|
|
|
Kinetic.Type._getImage(imageData, function(imageObj) {
|
2012-07-17 15:32:26 +08:00
|
|
|
that.setImage(imageObj);
|
|
|
|
|
2012-11-16 13:51:33 +08:00
|
|
|
if(callback) {
|
|
|
|
callback();
|
2012-07-17 15:32:26 +08:00
|
|
|
}
|
|
|
|
});
|
2012-11-13 11:59:19 +08:00
|
|
|
}
|
|
|
|
catch(e) {
|
2012-11-05 02:52:33 +08:00
|
|
|
Kinetic.Global.warn('Unable to apply filter. ' + e.message);
|
2012-07-17 15:32:26 +08:00
|
|
|
}
|
2012-08-16 14:13:50 +08:00
|
|
|
},
|
2012-09-25 11:34:23 +08:00
|
|
|
/**
|
|
|
|
* set crop
|
|
|
|
* @name setCrop
|
|
|
|
* @methodOf Kinetic.Image.prototype
|
|
|
|
* @param {Object|Array} config
|
|
|
|
* @param {Number} config.x
|
|
|
|
* @param {Number} config.y
|
|
|
|
* @param {Number} config.width
|
|
|
|
* @param {Number} config.height
|
|
|
|
*/
|
|
|
|
setCrop: function() {
|
2012-11-13 11:59:19 +08:00
|
|
|
var config = [].slice.call(arguments);
|
2012-09-25 11:34:23 +08:00
|
|
|
var pos = Kinetic.Type._getXY(config);
|
|
|
|
var size = Kinetic.Type._getSize(config);
|
|
|
|
var both = Kinetic.Type._merge(pos, size);
|
|
|
|
this.setAttr('crop', Kinetic.Type._merge(both, this.getCrop()));
|
|
|
|
},
|
2012-08-19 13:02:16 +08:00
|
|
|
/**
|
2012-08-22 10:42:29 +08:00
|
|
|
* create image buffer which enables more accurate hit detection mapping of the image
|
2012-08-19 13:02:16 +08:00
|
|
|
* by avoiding event detections for transparent pixels
|
2012-08-22 10:42:29 +08:00
|
|
|
* @name createImageBuffer
|
2012-08-19 13:02:16 +08:00
|
|
|
* @methodOf Kinetic.Image.prototype
|
|
|
|
* @param {Function} [callback] callback function to be called once
|
|
|
|
* the buffer image has been created and set
|
|
|
|
*/
|
2012-08-22 10:42:29 +08:00
|
|
|
createImageBuffer: function(callback) {
|
2012-08-19 13:02:16 +08:00
|
|
|
var canvas = new Kinetic.Canvas(this.attrs.width, this.attrs.height);
|
|
|
|
var context = canvas.getContext();
|
|
|
|
context.drawImage(this.attrs.image, 0, 0);
|
|
|
|
try {
|
|
|
|
var imageData = context.getImageData(0, 0, canvas.getWidth(), canvas.getHeight());
|
|
|
|
var data = imageData.data;
|
|
|
|
var rgbColorKey = Kinetic.Type._hexToRgb(this.colorKey);
|
|
|
|
// replace non transparent pixels with color key
|
|
|
|
for(var i = 0, n = data.length; i < n; i += 4) {
|
|
|
|
data[i] = rgbColorKey.r;
|
|
|
|
data[i + 1] = rgbColorKey.g;
|
|
|
|
data[i + 2] = rgbColorKey.b;
|
|
|
|
// i+3 is alpha (the fourth element)
|
|
|
|
}
|
|
|
|
|
|
|
|
var that = this;
|
|
|
|
Kinetic.Type._getImage(imageData, function(imageObj) {
|
2012-08-22 10:55:32 +08:00
|
|
|
that.imageBuffer = imageObj;
|
2012-08-19 13:02:16 +08:00
|
|
|
if(callback) {
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
});
|
2012-11-13 11:59:19 +08:00
|
|
|
}
|
|
|
|
catch(e) {
|
2012-08-22 10:55:32 +08:00
|
|
|
Kinetic.Global.warn('Unable to create image buffer.');
|
2012-08-19 13:02:16 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* clear buffer image
|
2012-08-22 10:55:32 +08:00
|
|
|
* @name clearImageBuffer
|
2012-08-19 13:02:16 +08:00
|
|
|
* @methodOf Kinetic.Image.prototype
|
|
|
|
*/
|
2012-08-22 10:55:32 +08:00
|
|
|
clearImageBuffer: function() {
|
|
|
|
delete this.imageBuffer;
|
2012-08-19 13:02:16 +08:00
|
|
|
},
|
2012-08-16 14:13:50 +08:00
|
|
|
_syncSize: function() {
|
|
|
|
if(this.attrs.image) {
|
|
|
|
if(!this.attrs.width) {
|
2012-09-25 11:34:23 +08:00
|
|
|
this.setWidth(this.attrs.image.width);
|
2012-08-16 14:13:50 +08:00
|
|
|
}
|
|
|
|
if(!this.attrs.height) {
|
2012-09-25 11:34:23 +08:00
|
|
|
this.setHeight(this.attrs.image.height);
|
2012-08-16 14:13:50 +08:00
|
|
|
}
|
|
|
|
}
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
2012-08-23 14:35:21 +08:00
|
|
|
};
|
|
|
|
Kinetic.Global.extend(Kinetic.Image, Kinetic.Shape);
|
2012-07-04 03:07:27 +08:00
|
|
|
|
|
|
|
// add getters setters
|
2012-10-11 10:25:50 +08:00
|
|
|
Kinetic.Node.addGettersSetters(Kinetic.Image, ['image']);
|
2012-09-25 11:34:23 +08:00
|
|
|
Kinetic.Node.addGetters(Kinetic.Image, ['crop']);
|
2012-06-11 04:07:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* set image
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setImage
|
|
|
|
* @methodOf Kinetic.Image.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {ImageObject} image
|
|
|
|
*/
|
|
|
|
|
2012-07-02 07:48:04 +08:00
|
|
|
/**
|
2012-07-17 15:32:26 +08:00
|
|
|
* get crop
|
|
|
|
* @name getCrop
|
2012-07-02 07:48:04 +08:00
|
|
|
* @methodOf Kinetic.Image.prototype
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2012-07-17 15:32:26 +08:00
|
|
|
* get image
|
|
|
|
* @name getImage
|
2012-07-02 07:48:04 +08:00
|
|
|
* @methodOf Kinetic.Image.prototype
|
2012-11-13 11:59:19 +08:00
|
|
|
*/
|