OLD | NEW |
(Empty) | |
| 1 var SVGSpriteSheet = require('./SVGSpriteSheet'); |
| 2 |
| 3 var Packer = { |
| 4 SpriteSortOrder: { |
| 5 // Sort by decreasing of sprite width |
| 6 Width: (a, b) => b.width - a.width || Packer._compareNames(a, b), |
| 7 // Sort by decreasing of sprite height |
| 8 Height: (a, b) => b.height - a.height || Packer._compareNames(a, b), |
| 9 // Sort by decreasing of sprite maxside |
| 10 MaxSide: (a, b) => Math.max(b.width, b.height) - Math.max(a.width, a.height)
|| Packer._compareNames(a, b), |
| 11 // Sort by decreasing of sprite area |
| 12 Area: (a, b) => b.width * b.height - a.width * a.height || Packer._compareNa
mes(a, b), |
| 13 }, |
| 14 |
| 15 /** |
| 16 * @param {!SVGSprite} spriteA |
| 17 * @param {!SVGSprite} spriteB |
| 18 * @return {number} |
| 19 */ |
| 20 _compareNames: function(spriteA, spriteB) { |
| 21 if (spriteA.filePath < spriteB.filePath) |
| 22 return -1; |
| 23 if (spriteA.filePath > spriteB.filePath) |
| 24 return 1; |
| 25 return 0; |
| 26 }, |
| 27 |
| 28 /** |
| 29 * @param {!Array<!SVGSprite>} sprites |
| 30 * @param {!Packer.SpriteSortOrder} spriteComparator |
| 31 * @param {number} rightPadding |
| 32 * @param {number} bottomPadding |
| 33 * @return {!SVGSpriteSheet} |
| 34 */ |
| 35 packSprites: function(sprites, spriteComparator, rightPadding, bottomPadding)
{ |
| 36 console.assert(sprites.length, 'cannot create spritesheet with 0 sprites!'); |
| 37 sprites.sort(spriteComparator); |
| 38 |
| 39 var totalWidth = sprites[0].width + rightPadding; |
| 40 var totalHeight = sprites[0].height + bottomPadding; |
| 41 /** @type {!Map<!SVGSprite, !{x: number, y: number}>} */ |
| 42 var positions = new Map(); |
| 43 |
| 44 var freeSpaces = new Set(); |
| 45 freeSpaces.add({x: 0, y: 0, width: totalWidth, height: totalHeight}); |
| 46 for (var sprite of sprites) { |
| 47 var spriteWidth = sprite.width + rightPadding; |
| 48 var spriteHeight = sprite.height + bottomPadding; |
| 49 var freeSpace = null; |
| 50 for (var space of freeSpaces) { |
| 51 if (space.width >= spriteWidth && space.height >= spriteHeight) { |
| 52 freeSpace = space; |
| 53 break; |
| 54 } |
| 55 } |
| 56 |
| 57 if (!freeSpace) { |
| 58 var canGrowRight = spriteHeight <= totalHeight; |
| 59 var canGrowDown = spriteWidth <= totalWidth; |
| 60 console.assert(canGrowDown || canGrowRight, 'cannot grow spritesheet in
either direction!'); |
| 61 // Lean towards square sprite sheet. |
| 62 var growRightAspectRatio = Math.abs(totalHeight / (totalWidth + spriteWi
dth) - 1); |
| 63 var growDownAspectRatio = Math.abs((totalHeight + spriteHeight) / totalW
idth - 1); |
| 64 if (!canGrowDown || (canGrowRight && growRightAspectRatio < growDownAspe
ctRatio)) { |
| 65 freeSpace = {x: totalWidth, y: 0, width: spriteWidth, height: totalHei
ght}; |
| 66 totalWidth += spriteWidth; |
| 67 } else { |
| 68 freeSpace = {x: 0, y: totalHeight, width: totalWidth, height: spriteHe
ight}; |
| 69 totalHeight += spriteHeight; |
| 70 } |
| 71 } else { |
| 72 freeSpaces.delete(freeSpace); |
| 73 } |
| 74 |
| 75 positions.set(sprite, {x: freeSpace.x, y: freeSpace.y}); |
| 76 |
| 77 var rightSpace = |
| 78 {x: freeSpace.x + spriteWidth, y: freeSpace.y, width: freeSpace.width
- spriteWidth, height: spriteHeight}; |
| 79 var downSpace = { |
| 80 x: freeSpace.x, |
| 81 y: freeSpace.y + spriteHeight, |
| 82 width: freeSpace.width, |
| 83 height: freeSpace.height - spriteHeight |
| 84 }; |
| 85 if (rightSpace.width && rightSpace.height) |
| 86 freeSpaces.add(rightSpace); |
| 87 if (downSpace.width && downSpace.height) |
| 88 freeSpaces.add(downSpace); |
| 89 } |
| 90 return new SVGSpriteSheet(totalWidth, totalHeight, positions); |
| 91 } |
| 92 }; |
| 93 |
| 94 module.exports = Packer; |
OLD | NEW |