styling
This commit is contained in:
parent
22696f3ec7
commit
394a6911bb
@ -125,8 +125,8 @@
|
||||
|
||||
<div class="slider-container" id="cropMarginWrap">
|
||||
<div class="control-label">CROP MARGIN <span class="unit">IN</span></div>
|
||||
<input type="range" class="slider" id="cropMargin" min="0" max="5" step="0.1" value="0" />
|
||||
<div class="slider-value" id="cropMarginVal">0.0 IN</div>
|
||||
<input type="range" class="slider" id="cropMargin" min="0" max="2" step="0.25" value="0" />
|
||||
<div class="slider-value" id="cropMarginVal">0.00</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -140,15 +140,14 @@
|
||||
<button class="reset-btn" id="reset">✕ CLEAR</button>
|
||||
|
||||
<div class="status" id="status"></div>
|
||||
<div class="hint" id="hint"></div>
|
||||
|
||||
</aside>
|
||||
|
||||
<!-- ============ PREVIEW ============ -->
|
||||
<main class="preview-container panel">
|
||||
<div class="preview-tabs">
|
||||
<button class="preview-tab active" id="tabOriginal" data-view="original" disabled>ORIGINAL</button>
|
||||
<button class="preview-tab" id="tabResult" data-view="result" disabled>RESULT</button>
|
||||
<button class="preview-tab active" id="tabInput" data-view="input" disabled>INPUT [I]</button>
|
||||
<button class="preview-tab" id="tabOutput" data-view="output" disabled>OUTPUT [O]</button>
|
||||
</div>
|
||||
<div class="preview-stage">
|
||||
<div class="no-preview" id="noPreview">[ NO IMAGE LOADED ]</div>
|
||||
@ -181,7 +180,6 @@ const go = $('go');
|
||||
const dl = $('dl');
|
||||
const dlbtn = $('dlbtn');
|
||||
const statusEl = $('status');
|
||||
const hint = $('hint');
|
||||
const reset = $('reset');
|
||||
const srcImg = $('src');
|
||||
const outImg = $('out');
|
||||
@ -201,17 +199,12 @@ const cropMarginWrap = $('cropMarginWrap');
|
||||
|
||||
const ctlAuto = $('ctl-auto');
|
||||
const ctlPrompt = $('ctl-prompt');
|
||||
const tabOriginal= $('tabOriginal');
|
||||
const tabResult = $('tabResult');
|
||||
const tabInput = $('tabInput');
|
||||
const tabOutput = $('tabOutput');
|
||||
|
||||
let selectedFile = null;
|
||||
let mode = 'auto';
|
||||
|
||||
const HINTS = {
|
||||
auto: 'Large or busy scenes segment best with HR at 2048+. The general model expects a clear single subject at 1024.',
|
||||
prompt: 'Type what to keep, e.g. "the dog" (or several: "cow. person."). Lower the box threshold to detect more / fainter objects.',
|
||||
};
|
||||
|
||||
/* ---- mode ---- */
|
||||
function setGroupEnabled(group, enabled) {
|
||||
group.classList.toggle('disabled', !enabled);
|
||||
@ -222,7 +215,6 @@ function setMode(m) {
|
||||
setGroupEnabled(ctlAuto, m === 'auto');
|
||||
setGroupEnabled(ctlPrompt, m === 'prompt');
|
||||
go.textContent = m === 'auto' ? 'REMOVE BACKGROUND' : 'SEGMENT';
|
||||
hint.textContent = HINTS[m];
|
||||
}
|
||||
document.querySelectorAll('input[name="mode"]').forEach(r =>
|
||||
r.addEventListener('change', () => setMode(r.value)));
|
||||
@ -248,7 +240,7 @@ wireSlider(boxThr, $('boxThrVal'), v => (+v).toFixed(2));
|
||||
wireSlider(textThr, $('textThrVal'), v => (+v).toFixed(2));
|
||||
wireSlider(maskOffset, $('maskOffsetVal'), v => (v > 0 ? '+' : '') + v);
|
||||
wireSlider(maskBlur, $('maskBlurVal'), v => String(v));
|
||||
wireSlider(cropMargin, $('cropMarginVal'), v => (+v).toFixed(1) + ' IN');
|
||||
wireSlider(cropMargin, $('cropMarginVal'), v => (+v).toFixed(2));
|
||||
|
||||
function syncCrop() {
|
||||
cropMarginWrap.classList.toggle('disabled', !cropChk.checked);
|
||||
@ -265,17 +257,17 @@ function setStatus(msg, isErr) {
|
||||
function refreshTabs() {
|
||||
const hasSrc = !!srcImg.getAttribute('src');
|
||||
const hasOut = !!outImg.getAttribute('src');
|
||||
tabOriginal.disabled = !hasSrc;
|
||||
tabResult.disabled = !hasOut;
|
||||
tabInput.disabled = !hasSrc;
|
||||
tabOutput.disabled = !hasOut;
|
||||
noPreview.hidden = hasSrc || hasOut;
|
||||
}
|
||||
function showView(v) {
|
||||
if ((v === 'original' && tabOriginal.disabled) ||
|
||||
(v === 'result' && tabResult.disabled)) return;
|
||||
tabOriginal.classList.toggle('active', v === 'original');
|
||||
tabResult.classList.toggle('active', v === 'result');
|
||||
srcImg.hidden = v !== 'original';
|
||||
outImg.hidden = v !== 'result';
|
||||
if ((v === 'input' && tabInput.disabled) ||
|
||||
(v === 'output' && tabOutput.disabled)) return;
|
||||
tabInput.classList.toggle('active', v === 'input');
|
||||
tabOutput.classList.toggle('active', v === 'output');
|
||||
srcImg.hidden = v !== 'input';
|
||||
outImg.hidden = v !== 'output';
|
||||
}
|
||||
document.querySelectorAll('.preview-tab').forEach(t =>
|
||||
t.addEventListener('click', () => showView(t.dataset.view)));
|
||||
@ -303,7 +295,7 @@ function pickFile(file) {
|
||||
go.disabled = false;
|
||||
setStatus('');
|
||||
refreshTabs();
|
||||
showView('original');
|
||||
showView('input');
|
||||
}
|
||||
|
||||
fileInput.addEventListener('change', e => pickFile(e.target.files[0]));
|
||||
@ -326,8 +318,8 @@ reset.addEventListener('click', () => {
|
||||
dlbtn.disabled = true;
|
||||
setStatus('');
|
||||
refreshTabs();
|
||||
tabOriginal.classList.add('active');
|
||||
tabResult.classList.remove('active');
|
||||
tabInput.classList.add('active');
|
||||
tabOutput.classList.remove('active');
|
||||
});
|
||||
|
||||
function fileToBase64(file) {
|
||||
@ -366,11 +358,13 @@ lightbox.addEventListener('mousedown', e => {
|
||||
});
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key === 'Escape' && !lightbox.hidden) closeLightbox();
|
||||
if ((e.key === 'b' || e.key === 'B') && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
||||
const t = e.target;
|
||||
if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT')) return;
|
||||
toggleSidebar();
|
||||
}
|
||||
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
||||
const t = e.target;
|
||||
if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT')) return;
|
||||
const k = e.key.toLowerCase();
|
||||
if (k === 'b') toggleSidebar();
|
||||
else if (k === 'i') showView('input');
|
||||
else if (k === 'o') showView('output');
|
||||
});
|
||||
|
||||
lbStage.addEventListener('wheel', e => {
|
||||
@ -448,7 +442,7 @@ go.addEventListener('click', async () => {
|
||||
dl.download = selectedFile.name.replace(/\.[^.]+$/, '') + '.png';
|
||||
dlbtn.disabled = false;
|
||||
refreshTabs();
|
||||
showView('result');
|
||||
showView('output');
|
||||
const secs = ((performance.now() - t0) / 1000).toFixed(1);
|
||||
if (mode === 'auto') {
|
||||
setStatus(`DONE — ${data.width}×${data.height} · ${data.model} @ ${data.resolution} · ${secs}S`);
|
||||
|
||||
@ -768,11 +768,11 @@ select option {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* breathing room between stacked controls inside the OUTPUT drawer */
|
||||
/* stack OUTPUT-drawer controls with the same 5px rhythm as .control-group */
|
||||
.drawer-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
/* --- help tooltip (carried over, restyled brutalist) --- */
|
||||
@ -800,7 +800,7 @@ select option {
|
||||
.help:hover::after {
|
||||
content: attr(data-tip);
|
||||
position: absolute;
|
||||
bottom: 150%;
|
||||
top: 150%;
|
||||
right: 0;
|
||||
width: 220px;
|
||||
background: #000000;
|
||||
@ -866,15 +866,6 @@ select option {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
.hint {
|
||||
font-size: 11px;
|
||||
color: #5a7a5a;
|
||||
line-height: 1.6;
|
||||
text-transform: none;
|
||||
border-left: 2px solid #2e3e2e;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
/* --- preview area --- */
|
||||
.preview-tabs {
|
||||
position: absolute;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user