mirror of
https://github.com/konvajs/konva.git
synced 2025-09-18 09:50:05 +08:00
refactored and optimized Image.js and Type.js
This commit is contained in:
@@ -154,7 +154,7 @@
|
||||
go._removeName(this.getName(), this._id);
|
||||
|
||||
// stop DD
|
||||
if(dd && dd.targetNode && dd.targetNode._id === this._id) {
|
||||
if(dd && dd.node && dd.node._id === this._id) {
|
||||
node._endDrag();
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,8 @@
|
||||
(function() {
|
||||
// CONSTANTS
|
||||
var IMAGE = 'Image',
|
||||
CROP = 'crop';
|
||||
|
||||
/**
|
||||
* Image constructor
|
||||
* @constructor
|
||||
@@ -15,38 +19,40 @@
|
||||
|
||||
Kinetic.Image.prototype = {
|
||||
_initImage: function(config) {
|
||||
var that = this;
|
||||
|
||||
// call super constructor
|
||||
Kinetic.Shape.call(this, config);
|
||||
this.shapeType = 'Image';
|
||||
this.shapeType = IMAGE;
|
||||
this._setDrawFuncs();
|
||||
|
||||
var that = this;
|
||||
this.on('imageChange', function(evt) {
|
||||
that._syncSize();
|
||||
});
|
||||
|
||||
this._syncSize();
|
||||
},
|
||||
drawFunc: function(canvas) {
|
||||
var width = this.getWidth(), height = this.getHeight(), params, that = this, context = canvas.getContext();
|
||||
var width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
params,
|
||||
that = this,
|
||||
context = canvas.getContext(),
|
||||
image = this.getImage(),
|
||||
crop = this.getCrop(),
|
||||
cropX, cropY, cropWidth, cropHeight;
|
||||
|
||||
context.beginPath();
|
||||
context.rect(0, 0, width, height);
|
||||
context.closePath();
|
||||
canvas.fillStroke(this);
|
||||
|
||||
if(this.attrs.image) {
|
||||
if(image) {
|
||||
// if cropping
|
||||
if(this.attrs.crop && this.attrs.crop.width && this.attrs.crop.height) {
|
||||
var cropX = this.attrs.crop.x || 0;
|
||||
var cropY = this.attrs.crop.y || 0;
|
||||
var cropWidth = this.attrs.crop.width;
|
||||
var cropHeight = this.attrs.crop.height;
|
||||
params = [this.attrs.image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height];
|
||||
if(crop) {
|
||||
cropX = crop.x || 0;
|
||||
cropY = crop.y || 0;
|
||||
cropWidth = crop.width || 0;
|
||||
cropHeight = crop.height || 0;
|
||||
params = [image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height];
|
||||
}
|
||||
// no cropping
|
||||
else {
|
||||
params = [this.attrs.image, 0, 0, width, height];
|
||||
params = [image, 0, 0, width, height];
|
||||
}
|
||||
|
||||
if(this.hasShadow()) {
|
||||
@@ -57,12 +63,13 @@
|
||||
else {
|
||||
this._drawImage(context, params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
drawHitFunc: function(canvas) {
|
||||
var width = this.getWidth(), height = this.getHeight(), imageHitRegion = this.imageHitRegion, appliedShadow = false, context = canvas.getContext();
|
||||
var width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
imageHitRegion = this.imageHitRegion,
|
||||
context = canvas.getContext();
|
||||
|
||||
if(imageHitRegion) {
|
||||
context.drawImage(imageHitRegion, 0, 0, width, height);
|
||||
@@ -89,16 +96,17 @@
|
||||
* filter has been applied
|
||||
*/
|
||||
applyFilter: function(filter, config, callback) {
|
||||
var canvas = new Kinetic.Canvas(this.attrs.image.width, this.attrs.image.height);
|
||||
var context = canvas.getContext();
|
||||
context.drawImage(this.attrs.image, 0, 0);
|
||||
var image = this.getImage(),
|
||||
canvas = new Kinetic.Canvas(image.width, image.height),
|
||||
context = canvas.getContext(),
|
||||
that = this;
|
||||
|
||||
context.drawImage(image, 0, 0);
|
||||
try {
|
||||
var imageData = context.getImageData(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
filter(imageData, config);
|
||||
var that = this;
|
||||
Kinetic.Type._getImage(imageData, function(imageObj) {
|
||||
that.setImage(imageObj);
|
||||
|
||||
if(callback) {
|
||||
callback();
|
||||
}
|
||||
@@ -119,11 +127,12 @@
|
||||
* @param {Number} config.height
|
||||
*/
|
||||
setCrop: function() {
|
||||
var config = [].slice.call(arguments);
|
||||
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()));
|
||||
var config = [].slice.call(arguments),
|
||||
pos = Kinetic.Type._getXY(config),
|
||||
size = Kinetic.Type._getSize(config),
|
||||
both = Kinetic.Type._merge(pos, size);
|
||||
|
||||
this.setAttr(CROP, Kinetic.Type._merge(both, this.getCrop()));
|
||||
},
|
||||
/**
|
||||
* create image hit region which enables more accurate hit detection mapping of the image
|
||||
@@ -134,22 +143,33 @@
|
||||
* the image hit region has been created
|
||||
*/
|
||||
createImageHitRegion: function(callback) {
|
||||
var canvas = new Kinetic.Canvas(this.attrs.width, this.attrs.height);
|
||||
var context = canvas.getContext();
|
||||
context.drawImage(this.attrs.image, 0, 0);
|
||||
var that = this,
|
||||
width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
canvas = new Kinetic.Canvas({
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
context = canvas.getContext(),
|
||||
image = this.getImage(),
|
||||
imageData, data, rgbColorKey, i, n;
|
||||
|
||||
context.drawImage(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);
|
||||
imageData = context.getImageData(0, 0, width, height);
|
||||
data = imageData.data;
|
||||
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)
|
||||
for(i = 0, n = data.length; i < n; i += 4) {
|
||||
if (data[i + 3] > 0) {
|
||||
data[i] = rgbColorKey.r;
|
||||
data[i + 1] = rgbColorKey.g;
|
||||
data[i + 2] = rgbColorKey.b;
|
||||
}
|
||||
}
|
||||
|
||||
var that = this;
|
||||
Kinetic.Type._getImage(imageData, function(imageObj) {
|
||||
that.imageHitRegion = imageObj;
|
||||
if(callback) {
|
||||
@@ -169,15 +189,13 @@
|
||||
clearImageHitRegion: function() {
|
||||
delete this.imageHitRegion;
|
||||
},
|
||||
_syncSize: function() {
|
||||
if(this.attrs.image) {
|
||||
if(!this.attrs.width) {
|
||||
this.setWidth(this.attrs.image.width);
|
||||
}
|
||||
if(!this.attrs.height) {
|
||||
this.setHeight(this.attrs.image.height);
|
||||
}
|
||||
}
|
||||
getWidth: function() {
|
||||
var image = this.getImage();
|
||||
return this.attrs.width || image.width || 0;
|
||||
},
|
||||
getHeight: function() {
|
||||
var image = this.getImage();
|
||||
return this.attrs.height || image.height || 0;
|
||||
},
|
||||
_drawImage: function(context, a) {
|
||||
if(a.length === 5) {
|
||||
|
@@ -1,4 +1,13 @@
|
||||
(function() {
|
||||
// CONSTANTS
|
||||
var CANVAS = 'canvas',
|
||||
CONTEXT_2D = '2d',
|
||||
OBJECT_ARRAY = '[object Array]',
|
||||
OBJECT_NUMBER = '[object Number]',
|
||||
OBJECT_STRING = '[object String]',
|
||||
PI_OVER_DEG180 = Math.PI / 180,
|
||||
DEG180_OVER_PI = 180 / Math.PI;
|
||||
|
||||
/*
|
||||
* utilities that handle data type detection, conversion, and manipulation
|
||||
*/
|
||||
@@ -16,27 +25,30 @@
|
||||
return (!!obj && obj.constructor == Object);
|
||||
},
|
||||
_isArray: function(obj) {
|
||||
return Object.prototype.toString.call(obj) == '[object Array]';
|
||||
return Object.prototype.toString.call(obj) == OBJECT_ARRAY;
|
||||
},
|
||||
_isNumber: function(obj) {
|
||||
return Object.prototype.toString.call(obj) == '[object Number]';
|
||||
return Object.prototype.toString.call(obj) == OBJECT_NUMBER;
|
||||
},
|
||||
_isString: function(obj) {
|
||||
return Object.prototype.toString.call(obj) == '[object String]';
|
||||
return Object.prototype.toString.call(obj) == OBJECT_STRING;
|
||||
},
|
||||
/*
|
||||
* other utils
|
||||
*/
|
||||
_hasMethods: function(obj) {
|
||||
var names = [];
|
||||
for(var key in obj) {
|
||||
if(this._isFunction(obj[key]))
|
||||
var names = [],
|
||||
key;
|
||||
|
||||
for(key in obj) {
|
||||
if(this._isFunction(obj[key])) {
|
||||
names.push(key);
|
||||
}
|
||||
}
|
||||
return names.length > 0;
|
||||
},
|
||||
_isInDocument: function(el) {
|
||||
while( el = el.parentNode) {
|
||||
while(el = el.parentNode) {
|
||||
if(el == document) {
|
||||
return true;
|
||||
}
|
||||
@@ -229,6 +241,8 @@
|
||||
* arg can be an image object or image data
|
||||
*/
|
||||
_getImage: function(arg, callback) {
|
||||
var imageObj, canvas, context, dataUrl;
|
||||
|
||||
// if arg is null or undefined
|
||||
if(!arg) {
|
||||
callback(null);
|
||||
@@ -241,8 +255,7 @@
|
||||
|
||||
// if arg is a string, then it's a data url
|
||||
else if(this._isString(arg)) {
|
||||
var imageObj = new Image();
|
||||
/** @ignore */
|
||||
imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
callback(imageObj);
|
||||
}
|
||||
@@ -251,14 +264,13 @@
|
||||
|
||||
//if arg is an object that contains the data property, it's an image object
|
||||
else if(arg.data) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas = document.createElement(CANVAS);
|
||||
canvas.width = arg.width;
|
||||
canvas.height = arg.height;
|
||||
var context = canvas.getContext('2d');
|
||||
context = canvas.getContext(CONTEXT_2D);
|
||||
context.putImageData(arg, 0, 0);
|
||||
var dataUrl = canvas.toDataURL();
|
||||
var imageObj = new Image();
|
||||
/** @ignore */
|
||||
dataUrl = canvas.toDataURL();
|
||||
imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
callback(imageObj);
|
||||
}
|
||||
@@ -280,9 +292,10 @@
|
||||
};
|
||||
},
|
||||
_getRandomColorKey: function() {
|
||||
var r = (Math.random() * 255) | 0;
|
||||
var g = (Math.random() * 255) | 0;
|
||||
var b = (Math.random() * 255) | 0;
|
||||
var r = (Math.random() * 255) | 0,
|
||||
g = (Math.random() * 255) | 0,
|
||||
b = (Math.random() * 255) | 0;
|
||||
|
||||
return this._rgbToHex(r, g, b);
|
||||
},
|
||||
// o1 takes precedence over o2
|
||||
@@ -312,10 +325,10 @@
|
||||
return retObj;
|
||||
},
|
||||
_degToRad: function(deg) {
|
||||
return deg * Math.PI / 180;
|
||||
return deg * PI_OVER_DEG180;
|
||||
},
|
||||
_radToDeg: function(rad) {
|
||||
return rad * 180 / Math.PI;
|
||||
return rad * DEG180_OVER_PI;
|
||||
},
|
||||
_capitalize: function(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
|
Reference in New Issue
Block a user