<div class="row" id="row">
<div class="frame"><canvas></canvas><span class="lbl">1:1</span></div>
<div class="frame"><canvas></canvas><span class="lbl">3:4</span></div>
<div class="frame"><canvas></canvas><span class="lbl">16:9</span></div>
<div class="frame"><canvas></canvas><span class="lbl">9:16</span></div>
<div class="frame bad"><canvas></canvas><span class="lbl">비율 무시</span></div>
</div>
.row{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;height:100%;padding:0 6px;flex-wrap:nowrap}
.frame{display:flex;flex-direction:column;align-items:center;gap:3px;flex-shrink:0}
.frame canvas{display:block;border-radius:5px;border:1.5px solid var(--line)}
.frame.bad canvas{border-color:var(--accent-2)}
.lbl{font-size:8.5px;color:var(--muted);font-weight:700;white-space:nowrap}
function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
function paintScene(ctx, w, h, seed) {
const r = mulberry32(seed);
const g = ctx.createLinearGradient(0, 0, 0, h);
g.addColorStop(0, 'hsl(200 55% 68%)'); g.addColorStop(1, 'hsl(210 40% 35%)');
ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
ctx.beginPath(); ctx.arc(w * 0.68, h * 0.22, Math.min(w, h) * 0.1, 0, Math.PI * 2); ctx.fillStyle = 'hsl(45 90% 78%)'; ctx.fill();
for (let l = 0; l < 2; l++) {
ctx.beginPath(); ctx.moveTo(0, h);
for (let i = 0; i <= 6; i++) { const x = w * i / 6; const y = h * (0.55 + l * 0.16) - r() * h * 0.12; ctx.lineTo(x, y); }
ctx.lineTo(w, h); ctx.closePath();
ctx.fillStyle = 'hsl(150 35% ' + (22 + l * 13) + '%)'; ctx.fill();
}
}
// 박스 종횡비 목록. 마지막(비율 무시)은 정사각형 내용을 이 비율의 박스에 강제로 눌러 담아 왜곡을 보여준다.
const ratios = [1, 0.75, 1.78, 0.56, 1.35];
const BAD = ratios.length - 1;
const frameEls = [...document.querySelectorAll('.frame')];
function layout(seed) {
const gap = 6, n = ratios.length;
const totalRatio = ratios.reduce((s, r) => s + r, 0);
const availW = innerWidth - 12;
const maxH = innerHeight * 0.68;
const H = Math.max(20, Math.min(maxH, (availW - gap * (n - 1)) / totalRatio));
frameEls.forEach((f, i) => {
const cv = f.querySelector('canvas');
const boxW = Math.round(H * ratios[i]), boxH = Math.round(H);
cv.style.width = boxW + 'px'; cv.style.height = boxH + 'px';
if (i === BAD) {
// 내용은 정사각형으로 그리고, 표시 박스만 다른 비율 — 캔버스가 자동으로 눌려 찌그러진다
cv.width = Math.round(H); cv.height = Math.round(H);
} else {
cv.width = boxW; cv.height = boxH;
}
paintScene(cv.getContext('2d'), cv.width, cv.height, seed);
});
}
const seeds = [3, 17];
let si = 0;
layout(seeds[si]);
addEventListener('resize', () => layout(seeds[si]));
setInterval(() => { si = (si + 1) % seeds.length; layout(seeds[si]); }, 3000);