konva/src/util/Type.js

322 lines
11 KiB
JavaScript
Raw Normal View History

(function() {
/*
* utilities that handle data type detection, conversion, and manipulation
*/
Kinetic.Type = {
/*
* cherry-picked utilities from underscore.js
*/
_isElement: function(obj) {
return !!(obj && obj.nodeType == 1);
},
_isFunction: function(obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
},
_isObject: function(obj) {
return (!!obj && obj.constructor == Object);
},
_isArray: function(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
},
_isNumber: function(obj) {
return Object.prototype.toString.call(obj) == '[object Number]';
},
_isString: function(obj) {
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]))
names.push(key);
}
return names.length > 0;
},
_isInDocument: function(el) {
while( el = el.parentNode) {
if(el == document) {
return true;
}
}
return false;
},
/*
* The argument can be:
* - an integer (will be applied to both x and y)
* - an array of one integer (will be applied to both x and y)
* - an array of two integers (contains x and y)
* - an array of four integers (contains x, y, width, and height)
* - an object with x and y properties
* - an array of one element which is an array of integers
* - an array of one element of an object
*/
_getXY: function(arg) {
if(this._isNumber(arg)) {
return {
x: arg,
y: arg
};
}
else if(this._isArray(arg)) {
// if arg is an array of one element
if(arg.length === 1) {
var val = arg[0];
// if arg is an array of one element which is a number
if(this._isNumber(val)) {
return {
x: val,
y: val
};
}
// if arg is an array of one element which is an array
else if(this._isArray(val)) {
return {
x: val[0],
y: val[1]
};
}
// if arg is an array of one element which is an object
else if(this._isObject(val)) {
return val;
}
}
// if arg is an array of two or more elements
else if(arg.length >= 2) {
return {
x: arg[0],
y: arg[1]
};
}
}
// if arg is an object return the object
else if(this._isObject(arg)) {
return arg;
}
// default
return null;
},
/*
* The argument can be:
* - an integer (will be applied to both width and height)
* - an array of one integer (will be applied to both width and height)
* - an array of two integers (contains width and height)
* - an array of four integers (contains x, y, width, and height)
* - an object with width and height properties
* - an array of one element which is an array of integers
* - an array of one element of an object
*/
_getSize: function(arg) {
if(this._isNumber(arg)) {
return {
width: arg,
height: arg
};
}
else if(this._isArray(arg)) {
// if arg is an array of one element
if(arg.length === 1) {
var val = arg[0];
// if arg is an array of one element which is a number
if(this._isNumber(val)) {
return {
width: val,
height: val
};
}
// if arg is an array of one element which is an array
else if(this._isArray(val)) {
/*
* if arg is an array of one element which is an
* array of four elements
*/
if(val.length >= 4) {
return {
width: val[2],
height: val[3]
};
}
/*
* if arg is an array of one element which is an
* array of two elements
*/
else if(val.length >= 2) {
return {
width: val[0],
height: val[1]
};
}
}
// if arg is an array of one element which is an object
else if(this._isObject(val)) {
return val;
}
}
// if arg is an array of four elements
else if(arg.length >= 4) {
return {
width: arg[2],
height: arg[3]
};
}
// if arg is an array of two elements
else if(arg.length >= 2) {
return {
width: arg[0],
height: arg[1]
};
}
}
// if arg is an object return the object
else if(this._isObject(arg)) {
return arg;
}
// default
return null;
},
/*
* arg will be an array of numbers or
* an array of point arrays or
* an array of point objects
*/
_getPoints: function(arg) {
if(arg === undefined) {
return [];
}
// an array of arrays
if(this._isArray(arg[0])) {
/*
* convert array of arrays into an array
* of objects containing x, y
*/
var arr = [];
for(var n = 0; n < arg.length; n++) {
arr.push({
x: arg[n][0],
y: arg[n][1]
});
}
return arr;
}
// an array of objects
if(this._isObject(arg[0])) {
return arg;
}
// an array of integers
else {
/*
* convert array of numbers into an array
* of objects containing x, y
*/
var arr = [];
for(var n = 0; n < arg.length; n += 2) {
arr.push({
x: arg[n],
y: arg[n + 1]
});
}
return arr;
}
},
/*
* arg can be an image object or image data
*/
_getImage: function(arg, callback) {
// if arg is null or undefined
if(!arg) {
callback(null);
}
// if arg is already an image object
else if(this._isElement(arg)) {
callback(arg);
}
// if arg is a string, then it's a data url
else if(this._isString(arg)) {
var imageObj = new Image();
/** @ignore */
imageObj.onload = function() {
callback(imageObj);
}
imageObj.src = arg;
}
//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.width = arg.width;
canvas.height = arg.height;
var context = canvas.getContext('2d');
context.putImageData(arg, 0, 0);
var dataUrl = canvas.toDataURL();
var imageObj = new Image();
/** @ignore */
imageObj.onload = function() {
callback(imageObj);
}
imageObj.src = dataUrl;
}
else {
callback(null);
}
},
_rgbToHex: function(r, g, b) {
return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
},
_hexToRgb: function(hex) {
var bigint = parseInt(hex, 16);
return {
r: (bigint >> 16) & 255,
g: (bigint >> 8) & 255,
b: bigint & 255
};
},
_getRandomColorKey: function() {
var r = (Math.random() * 255) | 0;
var g = (Math.random() * 255) | 0;
var b = (Math.random() * 255) | 0;
return this._rgbToHex(r, g, b);
},
// o1 takes precedence over o2
_merge: function(o1, o2) {
var retObj = this._clone(o2);
for(var key in o1) {
if(this._isObject(o1[key])) {
retObj[key] = this._merge(o1[key], retObj[key]);
}
else {
retObj[key] = o1[key];
}
}
return retObj;
},
// deep clone
_clone: function(obj) {
var retObj = {};
for(var key in obj) {
if(this._isObject(obj[key])) {
retObj[key] = this._clone(obj[key]);
}
else {
retObj[key] = obj[key];
}
}
return retObj;
},
_degToRad: function(deg) {
return deg * Math.PI / 180;
},
_radToDeg: function(rad) {
return rad * 180 / Math.PI;
}
};
})();