layout
Version:
Organize and layout items based on various algorithms
124 lines (112 loc) • 3.44 kB
JavaScript
function PackingSmith(algorithm, options) {
// Define items and save algorithm for later
this.items = [];
this.algorithm = algorithm;
// Fallback options and determine whether to sort or not
options = options || {};
var sort = options.sort !== undefined ? options.sort : true;
this.sort = sort;
}
PackingSmith.prototype = {
/**
* @param {Object} item Item to store -- this currently is mutated in-memory
* @param {Number} item.width Width of the item
* @param {Number} item.height Height of the item
* @param {Mixed} [item.meta] Any meta data you would like to store related to the item
*/
'addItem': function (item) {
// Save the item for later
this.items.push(item);
},
// Method to normalize coordinates to 0, 0
// This is bad to do mid-addition since it messes up the algorithm
'normalizeCoordinates': function () {
// Grab the items
var items = this.items;
// Find the most negative x and y
var minX = Infinity,
minY = Infinity;
items.forEach(function (item) {
var coords = item;
minX = Math.min(minX, coords.x);
minY = Math.min(minY, coords.y);
});
// Offset each item by -minX, -minY; effectively resetting to 0, 0
items.forEach(function (item) {
var coords = item;
coords.x -= minX;
coords.y -= minY;
});
},
'getStats': function () {
// Get the endX and endY for each item
var items = this.items,
coordsArr = items.map(function (item) {
return item;
}),
minXArr = coordsArr.map(function (coords) {
return coords.x;
}),
minYArr = coordsArr.map(function (coords) {
return coords.y;
}),
maxXArr = coordsArr.map(function (coords) {
return coords.x + coords.width;
}),
maxYArr = coordsArr.map(function (coords) {
return coords.y + coords.height;
});
// Get the maximums of these
var retObj = {
'minX': Math.max.apply(Math, minXArr),
'minY': Math.max.apply(Math, minYArr),
'maxX': Math.max.apply(Math, maxXArr),
'maxY': Math.max.apply(Math, maxYArr)
};
// Return the stats
return retObj;
},
'getItems': function () {
return this.items;
},
'processItems': function () {
// Run the items through our algorithm
var items = this.items;
if (this.sort) {
items = this.algorithm.sort(items);
}
items = this.algorithm.placeItems(items);
// Save the items for later
this.items = items;
// Return the items
return items;
},
'exportItems': function () {
// Process the items
this.processItems();
// Normalize the coordinates to 0, 0
this.normalizeCoordinates();
// Return the packed items
return this.items;
},
/**
* @returns {Object} retObj
* @returns {Number} retObj.height Height of the processed layout
* @returns {Number} retObj.width Width of the processed layout
* @returns {Mixed[]} retObj.items Organized items
*/
'export': function () {
// Grab the stats, coordinates, and items
var items = this.exportItems(),
stats = this.getStats();
// Generate and return our retObj
var retObj = {
'height': stats.maxY,
'width': stats.maxX,
'items': items
};
return retObj;
}
};
// Export PackingSmith
module.exports = PackingSmith;