|
1 | 1 | const keys = ['WO', 'FC', 'DR', 'MA']; |
2 | 2 | const keyDisplayNames = { WO: 'CODE', FC: 'DESIGN', DR: 'PITCH', MA: 'SHIP' }; |
| 3 | +const keyDisplayNamesMobile = { WO: 'CD', FC: 'DS', DR: 'PT', MA: 'SH' }; |
3 | 4 | const maxLidAngle = 45; |
4 | 5 | const closedLidAngle = 180; |
5 | 6 | const maxShowTime = 1000; |
@@ -147,24 +148,44 @@ class Bin { |
147 | 148 | } |
148 | 149 |
|
149 | 150 | writeIndex() { |
150 | | - g.textSize(18); |
| 151 | + const isMobile = g.width < 500; |
| 152 | + g.textSize(isMobile ? 16 : 18); |
151 | 153 | g.textFont('Arial'); |
| 154 | + g.textStyle(BOLD); |
152 | 155 | g.textAlign(CENTER, CENTER); |
153 | 156 | g.fill(palette.FG); |
154 | | - g.noStroke(); |
| 157 | + if (isMobile) { |
| 158 | + g.stroke(palette.FG); |
| 159 | + g.strokeWeight(1.5); |
| 160 | + } else { |
| 161 | + g.noStroke(); |
| 162 | + } |
155 | 163 | g.text(nf(this.i, 2, 0), this.x, this.y); |
| 164 | + g.textStyle(NORMAL); |
| 165 | + g.noStroke(); |
156 | 166 | } |
157 | 167 |
|
158 | 168 | writePercentage(perc, rw, buffer) { |
| 169 | + const isMobile = g.width < 500; |
159 | 170 | g.textAlign(LEFT, CENTER); |
160 | | - g.stroke(palette.FG); |
161 | | - g.strokeWeight(2); |
162 | | - g.fill(palette.BG); |
| 171 | + g.textStyle(BOLD); |
| 172 | + if (isMobile) { |
| 173 | + g.fill(palette.FG); |
| 174 | + g.stroke(palette.FG); |
| 175 | + g.strokeWeight(1); |
| 176 | + g.textSize(max(10, buffer * 0.1)); |
| 177 | + } else { |
| 178 | + g.stroke(palette.FG); |
| 179 | + g.strokeWeight(2); |
| 180 | + g.fill(palette.BG); |
| 181 | + } |
163 | 182 | g.text( |
164 | 183 | `${floor(nf(100 * perc, 2, 0))}%`, |
165 | 184 | this.x - rw * 0.45, |
166 | 185 | this.y + buffer * 0.3 |
167 | 186 | ); |
| 187 | + g.textStyle(NORMAL); |
| 188 | + g.noStroke(); |
168 | 189 | } |
169 | 190 |
|
170 | 191 | drawLevels(rw, buffer) { |
@@ -240,43 +261,74 @@ class Bin { |
240 | 261 |
|
241 | 262 | drawLevel(i, y, rw, buffer) { |
242 | 263 | const level = keys[i - 1]; |
243 | | - const displayName = keyDisplayNames[level]; |
| 264 | + const isMobile = g.width < 500; |
| 265 | + const displayName = isMobile ? keyDisplayNamesMobile[level] : keyDisplayNames[level]; |
244 | 266 | const levelColor = palette.LEVELS[level]; |
245 | 267 |
|
246 | 268 | g.rectMode(CORNER); |
247 | 269 | g.stroke(levelColor); |
248 | 270 | g.noFill(); |
249 | 271 |
|
250 | | - // Draw the label for the progress bar using display name. |
251 | | - g.textAlign(LEFT, CENTER); |
252 | | - g.noStroke(); |
253 | | - g.fill(levelColor); |
254 | | - g.textFont("Courier"); |
255 | | - g.textSize(min(14, buffer * 0.14)); |
256 | | - const labelW = g.textWidth(displayName); |
257 | | - const barX = this.x - rw * 0.45 + labelW + rw * 0.04; |
258 | | - const barW = this.x + rw * 0.45 - barX; |
259 | | - |
260 | | - g.text( |
261 | | - displayName, |
262 | | - this.x - rw * 0.45, |
263 | | - y - buffer + i * buffer * 0.35 + buffer * 0.075 |
264 | | - ); |
| 272 | + if (isMobile) { |
| 273 | + // Mobile: label above a full-width bar, bold and readable |
| 274 | + const rowH = buffer * 0.35; |
| 275 | + const rowY = y - buffer + i * rowH; |
| 276 | + |
| 277 | + g.textAlign(CENTER, TOP); |
| 278 | + g.fill(levelColor); |
| 279 | + g.stroke(levelColor); |
| 280 | + g.strokeWeight(1.5); |
| 281 | + g.textFont("Arial"); |
| 282 | + g.textStyle(BOLD); |
| 283 | + g.textSize(max(10, buffer * 0.1)); |
| 284 | + g.text(displayName, this.x, rowY); |
| 285 | + g.noStroke(); |
| 286 | + |
| 287 | + // Progress bar below label |
| 288 | + const barY = rowY + buffer * 0.12; |
| 289 | + const barH = buffer * 0.1; |
| 290 | + const barX = this.x - rw * 0.45; |
| 291 | + const barW = rw * 0.9; |
| 292 | + g.stroke(levelColor); |
| 293 | + g.noFill(); |
| 294 | + g.rect(barX, barY, barW, barH); |
| 295 | + g.fill(levelColor); |
| 296 | + g.noStroke(); |
| 297 | + let w = (barW * this.levels[level]) / this.levelGoal; |
| 298 | + g.rect(barX, barY, w, barH); |
| 299 | + g.textStyle(NORMAL); |
| 300 | + } else { |
| 301 | + // Desktop: label + bar side by side (unchanged) |
| 302 | + g.textAlign(LEFT, CENTER); |
| 303 | + g.noStroke(); |
| 304 | + g.fill(levelColor); |
| 305 | + g.textFont("Courier"); |
| 306 | + g.textSize(min(14, buffer * 0.14)); |
| 307 | + const labelW = g.textWidth(displayName); |
| 308 | + const barX = this.x - rw * 0.45 + labelW + rw * 0.04; |
| 309 | + const barW = this.x + rw * 0.45 - barX; |
| 310 | + |
| 311 | + g.text( |
| 312 | + displayName, |
| 313 | + this.x - rw * 0.45, |
| 314 | + y - buffer + i * buffer * 0.35 + buffer * 0.075 |
| 315 | + ); |
265 | 316 |
|
266 | | - // Draw the outline of the progress bar |
267 | | - g.rectMode(CORNER); |
268 | | - g.stroke(levelColor); |
269 | | - g.noFill(); |
270 | | - g.rect( |
271 | | - barX, |
272 | | - y - buffer + i * buffer * 0.35, |
273 | | - barW, |
274 | | - buffer * 0.15 |
275 | | - ); |
276 | | - // Draw the filled bar inside of the progress bar. |
277 | | - g.fill(levelColor); |
278 | | - let w = (barW * this.levels[level]) / this.levelGoal; |
279 | | - g.rect(barX, y - buffer + i * buffer * 0.35, w, buffer * 0.15); |
| 317 | + // Draw the outline of the progress bar |
| 318 | + g.rectMode(CORNER); |
| 319 | + g.stroke(levelColor); |
| 320 | + g.noFill(); |
| 321 | + g.rect( |
| 322 | + barX, |
| 323 | + y - buffer + i * buffer * 0.35, |
| 324 | + barW, |
| 325 | + buffer * 0.15 |
| 326 | + ); |
| 327 | + // Draw the filled bar inside of the progress bar. |
| 328 | + g.fill(levelColor); |
| 329 | + let w = (barW * this.levels[level]) / this.levelGoal; |
| 330 | + g.rect(barX, y - buffer + i * buffer * 0.35, w, buffer * 0.15); |
| 331 | + } |
280 | 332 | } |
281 | 333 |
|
282 | 334 | drawBinLids(rw, buffer) { |
|
0 commit comments