PageSourceSearch

https://jayreddinjr-jr-odysseus-hf.hf.space/static/js/editor/stroke-tool-sliders.js

js jayreddinjr-jr-odysseus-hf.hf.space collected 2026-10-04 17:01:23 UTC 3,297 bytes, 64 lines download raw bytes

1/**
2 * Per-tool stroke-modifier sliders (Opacity / Flow / Softness) for
3 * Eraser, Brush, and Clone. The three sections share identical UX:
4 *
5 *   - Opacity slider: writes to state, updates label, fades the
6 *     preview swatch opacity.
7 *   - Flow slider: writes to state, updates label, fades the swatch
8 *     opacity AND swaps its border style (dashed at low flow → dotted
9 *     at high flow) so the user sees the "denseness" change.
10 *   - Softness slider: writes to state, updates label, tweens the
11 *     radial-gradient inner stop on the swatch so it visually fades
12 *     from hard disk to soft falloff.
13 *
14 * The whole block was three near-identical 30-LOC copies before; now
15 * it's one helper that takes the tool's prefix + a state-field bag.
16 *
17 * Usage: just call wireStrokeToolSliders() — the DOM IDs are wired
18 * statically from #ge-{eraser,brush,clone}-{opacity,flow,softness}
19 * + their labels + preview swatches.
20 */
21import { state } from './state.js';
22
23/** Wire the three sliders for one stroke tool. */
24function wireToolSliders(prefix, fields) {
25  const opPrev   = document.getElementById(`ge-${prefix}-preview-opacity`);
26  const flPrev   = document.getElementById(`ge-${prefix}-preview-flow`);
27  const softPrev = document.getElementById(`ge-${prefix}-preview-softness`);
28
29  document.getElementById(`ge-${prefix}-opacity`)?.addEventListener('input', (e) => {
30    state[fields.opacity] = parseInt(e.target.value);
31    document.getElementById(`ge-${prefix}-opacity-label`).textContent = state[fields.opacity] + '%';
32    if (opPrev) opPrev.style.opacity = (state[fields.opacity] / 100).toFixed(2);
33  });
34
35  document.getElementById(`ge-${prefix}-flow`)?.addEventListener('input', (e) => {
36    state[fields.flow] = parseInt(e.target.value);
37    document.getElementById(`ge-${prefix}-flow-label`).textContent = state[fields.flow] + '%';
38    // Lower flow → fewer / sparser dots. Cycle dot densities by
39    // swapping the dashed/dotted border style and fading opacity.
40    if (flPrev) {
41      const denseness = Math.max(1, Math.round(state[fields.flow] / 20));
42      flPrev.style.borderStyle = denseness <= 2 ? 'dashed' : 'dotted';
43      flPrev.style.opacity = (0.3 + (state[fields.flow] / 100) * 0.6).toFixed(2);
44    }
45  });
46
47  document.getElementById(`ge-${prefix}-softness`)?.addEventListener('input', (e) => {
48    state[fields.softness] = parseInt(e.target.value);
49    document.getElementById(`ge-${prefix}-softness-label`).textContent = state[fields.softness] + '%';
50    // Preview tweens from a hard disk into a soft radial gradient as
51    // softness rises (the CSS already sets the radial gradient — we
52    // just tween the inner solid radius to communicate the falloff).
53    if (softPrev) {
54      const innerStop = Math.max(0, 60 - state[fields.softness] * 0.55);
55      softPrev.style.background = `radial-gradient(circle, var(--fg) 0%, var(--fg) ${innerStop}%, transparent 90%)`;
56    }
57  });
58}
59
60export function wireStrokeToolSliders() {
61  wireToolSliders('eraser', { opacity: 'eraserOpacity', flow: 'eraserFlow', softness: 'eraserSoftness' });
62  wireToolSliders('brush',  { opacity: 'brushOpacity',  flow: 'brushFlow',  softness: 'brushSoftness'  });
63  wireToolSliders('clone',  { opacity: 'cloneOpacity',  flow: 'cloneFlow',  softness: 'cloneSoftness'  });
64}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.