forked from draeton/stitches
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathicons.js
190 lines (159 loc) · 6.57 KB
/
icons.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// ## Stitches.Icons
//
// [http://draeton.github.com/stitches](http://draeton.github.com/stitches)
//
// Copyright 2011, Matthew Cobbs
// Licensed under the MIT license.
//
/*global jQuery, Stitches */
(function (window, Stitches, $) {
"use strict";
// ## Stitches.Icons namespace
//
// Holds all methods for working with icons
Stitches.Icons = (function () {
/* shortcut */
var S = window.Stitches;
/* shortcut */
var document = window.document;
return {
// ### idealCanvas
//
// Find the ideal sprite canvas
//
// @param {Array} icons A list of icons
// @return {HTMLCanvasElement}
idealCanvas: function (icons) {
var maxW = 0;
var maxH = 0;
var area = 0;
/* find the max height & width; the area is the sum of the areas
of the rectangles */
$(icons).each(function (idx, icon) {
maxW = icon.width > maxW ? icon.width : maxW;
maxH = icon.height > maxH ? icon.height : maxH;
area += icon.area;
});
/* ideal shape is a square, with sides the length of the square root of
the area */
var ideal = Math.ceil(Math.sqrt(area));
/* if there is a rectangle with a width or height greater than the square
root, increase the length of that side of the ideal square....
which I guess makes it an ideal rectangle */
var idealW = maxW > ideal ? maxW : ideal;
var idealH = maxH > ideal ? maxH : ideal;
/* create the sprite canvas */
var canvas = document.createElement("canvas");
canvas.width = idealW;
canvas.height = idealH;
return canvas;
},
// ### placeIcons
//
// Place icons within the sprite (the ideal square)
//
// @param {Array} loose All loose icons
// @param {Array} placed All placed icons
// @param {HTMLCanvasElement} canvas The working canvas
// @return {Boolean} Have all icons been placed?
placeIcons: function (loose, placed, canvas) {
var i = 0;
/* loop through all of the icons, attempting to place them within the sprite
without intersections */
while (loose.length && i < 10) {
$(loose).each(function (idx, icon) {
if (!icon.isPlaced) {
icon.isPlaced = S.Icons.placeIcon(icon, placed, canvas);
}
});
i++;
}
for (i = 0; i < loose.length; i++) {
if (loose[i].isPlaced) {
loose.splice(i);
}
}
/* done */
return true;
},
// ### placeIcon
//
// Place one icon on the sprite, checking for intersects with the sprite
// dimensions and other placed icons
//
// @param {Icon} icon The icon to place
// @param {Array} placed All placed icons
// @param {HTMLCanvasElement} canvas The working canvas
// @return {Boolean} Have this icon been placed?
placeIcon: function (icon, placed, canvas) {
var i = 0;
/* two tries to place the icon... */
while (i < 2) {
for (var y = 0; y <= canvas.height - icon.height; y++) {
for (var x = 0; x <= canvas.width - icon.width; x++) {
icon.x = x;
icon.y = y;
var overlap = S.Icons.isOverlapped(icon, placed);
if (!overlap) {
return true;
}
x = overlap.x + overlap.width;
}
y = overlap.y + overlap.height;
}
/* no room, so add the width of the icon */
canvas.width += icon.width;
canvas.height += icon.height;
i++;
}
/* if we made it here, place was unsuccessful */
return false;
},
// ### isOverlapped
//
// Check if this icon overlaps any of the placed icons. If not,
// add to the `placed` array
//
// @param {Icon} icon The icon to place
// @param {Array} placed All placed icons
// @return {Null|Object} Overlap coordinates, if overlap
isOverlapped: function (icon, placed) {
var x1, x2, y1, y2;
var intersect = [];
var overlap = null;
/* filter the checkPoints arrays based on currentIcon position */
$(placed).each(function (idx, p) {
x1 = (p.x < icon.x + icon.width);
x2 = (p.x + p.width > icon.x);
y1 = (p.y < icon.y + icon.height);
y2 = (p.y + p.height > icon.y);
if (x1 && x2 && y1 && y2) {
intersect.push(p);
}
});
/* if there are any items left in the intersect array, there has been an overlap */
if (intersect.length) {
overlap = intersect.pop();
} else {
placed.push(icon);
}
return overlap;
},
// ### cropCanvas
//
// Crop to content, after placing icons
//
// @param {Array} placed All placed icons
// @param {HTMLCanvasElement} canvas The working canvas
cropCanvas: function (placed, canvas) {
var w = 0, h = 0;
$(placed).each(function (idx, icon) {
w = w > icon.x + icon.width ? w : icon.x + icon.width;
h = h > icon.y + icon.height ? h : icon.y + icon.height;
});
canvas.width = w;
canvas.height = h;
}
};
})();
})(window, Stitches, jQuery);