fabric.js/src/util/misc.js

217 lines
6.5 KiB
JavaScript
Raw Normal View History

(function() {
/**
* @namespace
*/
fabric.util = { };
2010-06-09 22:34:55 +00:00
/**
* Removes value from an array.
2010-06-09 22:34:55 +00:00
* Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`
* @static
* @memberOf fabric.util
* @method removeFromArray
2010-06-09 22:34:55 +00:00
* @param {Array} array
* @param {Any} value
* @return {Array} original array
*/
function removeFromArray(array, value) {
var idx = array.indexOf(value);
if (idx !== -1) {
array.splice(idx, 1);
}
return array;
};
2010-06-09 22:34:55 +00:00
/**
* Returns random number between 2 specified ones.
2010-06-09 22:34:55 +00:00
* @static
* @method getRandomInt
* @memberOf fabric.util
2010-06-09 22:34:55 +00:00
* @param {Number} min lower limit
* @param {Number} max upper limit
* @return {Number} random value (between min and max)
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var PiBy180 = Math.PI / 180;
2010-06-09 22:34:55 +00:00
/**
* Transforms degrees to radians.
* @static
* @method degreesToRadians
* @memberOf fabric.util
2010-06-09 22:34:55 +00:00
* @param {Number} degrees value in degrees
* @return {Number} value in radians
*/
function degreesToRadians(degrees) {
return degrees * PiBy180;
}
2010-06-09 22:34:55 +00:00
/**
* A wrapper around Number#toFixed, which contrary to native method returns number, not string.
* @static
* @method toFixed
* @memberOf fabric.util
2010-06-09 22:34:55 +00:00
* @param {Number | String} number number to operate on
* @param {Number} fractionDigits number of fraction digits to "leave"
* @return {Number}
*/
function toFixed(number, fractionDigits) {
return parseFloat(Number(number).toFixed(fractionDigits));
}
/**
* Function which always returns `false`.
* @static
* @method falseFunction
* @memberOf fabric.util
* @return {Boolean}
*/
function falseFunction() {
return false;
}
/**
* Changes value from one to another within certain period of time, invoking callbacks as value is being changed.
* @method animate
* @memberOf fabric.util
* @param {Object} [options] Animation options
* @param {Function} [options.onChange] Callback; invoked on every value change
* @param {Function} [options.onComplete] Callback; invoked when value change is completed
* @param {Number} [options.startValue=0] Starting value
* @param {Number} [options.endValue=100] Ending value
* @param {Number} [options.byValue=100] Value to modify the property by
* @param {Function} [options.easing] Easing function
* @param {Number} [options.duration=500] Duration of change
*/
function animate(options) {
options || (options = { });
var start = +new Date(),
duration = options.duration || 500,
finish = start + duration, time, pos,
onChange = options.onChange || function() { },
abort = options.abort || function() { return false; },
2012-04-26 03:01:42 +00:00
easing = options.easing || function(t, b, c, d) {return -c * Math.cos(t/d * (Math.PI/2)) + c + b;},
startValue = 'startValue' in options ? options.startValue : 0,
endValue = 'endValue' in options ? options.endValue : 100;
byValue = options.byValue || endValue - startValue;
options.onStart && options.onStart();
(function tick() {
time = +new Date();
currentTime = time > finish ? duration : (time - start);
onChange(easing(currentTime, startValue, byValue, duration));
if (time > finish || abort()) {
options.onComplete && options.onComplete();
return;
}
requestAnimFrame(tick);
})();
}
var _requestAnimFrame = fabric.window.requestAnimationFrame ||
fabric.window.webkitRequestAnimationFrame ||
fabric.window.mozRequestAnimationFrame ||
fabric.window.oRequestAnimationFrame ||
fabric.window.msRequestAnimationFrame ||
function(callback, element) {
fabric.window.setTimeout(callback, 1000 / 60);
};
/**
* requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/
* @method requestAnimFrame
* @memberOf fabric.util
* @param {Function} callback Callback to invoke
* @param {DOMElement} element optional Element to associate with animation
*/
var requestAnimFrame = function() {
return _requestAnimFrame.apply(fabric.window, arguments);
};
/**
* Loads image element from given url and passes it to a callback
* @method loadImage
* @memberOf fabric.util
* @param {String} url URL representing an image
* @param {Function} callback Callback; invoked with loaded image
* @param {Any} context optional Context to invoke callback in
*/
function loadImage(url, callback, context) {
if (url) {
var img = new Image();
/** @ignore */
img.onload = function () {
callback && callback.call(context, img);
img = img.onload = null;
};
img.src = url;
}
else {
callback && callback.call(context, url);
}
}
function enlivenObjects(objects, callback) {
function getKlass(type) {
return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(type))];
}
2012-09-02 14:39:07 +00:00
function onLoaded() {
if (++numLoadedObjects === numTotalObjects) {
if (callback) {
callback(enlivenedObjects);
}
}
}
2012-09-02 14:39:07 +00:00
var enlivenedObjects = [ ],
numLoadedObjects = 0,
numTotalObjects = objects.length;
objects.forEach(function (o, index) {
if (!o.type) {
return;
}
var klass = getKlass(o.type);
if (klass.async) {
klass.fromObject(o, function (o) {
enlivenedObjects[index] = o;
2012-09-02 14:39:07 +00:00
onLoaded();
});
}
else {
enlivenedObjects[index] = klass.fromObject(o);
2012-09-02 14:39:07 +00:00
onLoaded();
}
});
}
function groupSVGElements(elements, options, path) {
var object = elements.length > 1
? new fabric.PathGroup(elements, options)
: elements[0];
if (typeof path !== 'undefined') {
object.setSourcePath(path);
}
return object;
}
fabric.util.removeFromArray = removeFromArray;
fabric.util.degreesToRadians = degreesToRadians;
fabric.util.toFixed = toFixed;
fabric.util.getRandomInt = getRandomInt;
fabric.util.falseFunction = falseFunction;
fabric.util.animate = animate;
fabric.util.requestAnimFrame = requestAnimFrame;
fabric.util.loadImage = loadImage;
fabric.util.enlivenObjects = enlivenObjects;
fabric.util.groupSVGElements = groupSVGElements;
})();