Exposure Slider New
An exposure dial like on a camera: drag the ruler under the marker and the preview gets lighter or darker. For photo editors, configurators and range settings.
±0,0 EV
How to use it
- Paste the HTML where the forms & inputs should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Exposure Slider · Bron: SmoothUI · licentie MIT. Laat deze vermelding staan bij hergebruik. -->
<div class="jouw-container">
<div class="exs"><div class="exs__view"><div class="exs__img"><span class="exs__win"></span><span class="exs__lamp"></span><span class="exs__sofa"></span></div><span class="exs__val">±0,0 EV</span></div><div class="exs__ruler" tabindex="0" role="slider" aria-label="Belichting" aria-valuemin="-3" aria-valuemax="3" aria-valuenow="0" aria-valuetext="0,0 EV"><canvas class="exs__cv"></canvas><span class="exs__mark"></span></div></div>
</div>/* Exposure Slider · Bron: SmoothUI · licentie MIT. Laat deze vermelding staan bij hergebruik. */
.exs{width:320px;max-width:90%;font-family:'Switzer',system-ui,sans-serif;display:flex;flex-direction:column;gap:10px}
.exs__view{position:relative;height:118px;border-radius:4px;overflow:hidden;background:#0a0a0a}
.exs__img{position:absolute;inset:0;background:linear-gradient(180deg,#a99a86 0,#988a77 64%,#6f5843 64%,#57442f 100%)}
.exs__win{position:absolute;left:12%;top:14%;width:26%;height:42%;background:linear-gradient(160deg,#f6e7cf,#d9a873);border:4px solid #d9d2c6;box-sizing:border-box}
.exs__lamp{position:absolute;right:20%;top:0;width:18px;height:40%;border-left:1px solid #0a0a0a;left:auto}
.exs__lamp::after{content:'';position:absolute;left:-14px;bottom:-4px;width:28px;height:16px;background:#F5480F;border-radius:14px 14px 2px 2px}
.exs__sofa{position:absolute;left:46%;bottom:22%;width:40%;height:24%;background:#0a0a0a;border-radius:4px 4px 2px 2px}
.exs__val{position:absolute;right:8px;top:8px;font:500 11px/1 'JetBrains Mono',monospace;letter-spacing:.06em;background:rgba(10,10,10,.75);color:#fff;padding:5px 7px;border-radius:3px;font-variant-numeric:tabular-nums}
.exs__ruler{position:relative;height:46px;background:#fff;border:1px solid rgba(10,10,10,.12);border-radius:4px;cursor:ew-resize;touch-action:none;user-select:none;-webkit-user-select:none;overflow:hidden}
.exs__ruler:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.exs__cv{position:absolute;inset:0;width:100%;height:100%}
.exs__mark{position:absolute;left:50%;top:0;bottom:0;width:2px;margin-left:-1px;background:#F5480F}
.exs__mark::before{content:'';position:absolute;left:-4px;top:0;border:5px solid transparent;border-top-color:#F5480F}// Exposure Slider · Bron: SmoothUI · licentie MIT. Laat deze vermelding staan bij hergebruik.
// root = het element waarin de HTML staat
function init(root){
var w = root.querySelector('.exs'); if (!w) return;
var ru = w.querySelector('.exs__ruler'), cv = w.querySelector('.exs__cv'), img = w.querySelector('.exs__img'), out = w.querySelector('.exs__val');
var v = 0, STEP = 9, dragging = false, x0 = 0, v0 = 0;
function fmt(n) { var s = Math.abs(n).toFixed(1).replace('.', ','); return (n > 0.04 ? '+' : n < -0.04 ? '−' : '±') + s; }
function draw() {
var d = Math.min(window.devicePixelRatio || 1, 2), W = ru.clientWidth, H = ru.clientHeight;
if (cv.width !== W * d) { cv.width = W * d; cv.height = H * d; }
var x = cv.getContext('2d'); x.setTransform(d, 0, 0, d, 0, 0); x.clearRect(0, 0, W, H);
x.font = "500 9px 'JetBrains Mono', monospace"; x.textAlign = 'center';
for (var i = -30; i <= 30; i++) {
var px = W / 2 + (i / 10 - v) * 10 * STEP; if (px < -10 || px > W + 10) continue;
var major = i % 10 === 0, half = i % 5 === 0;
x.fillStyle = major ? '#0a0a0a' : 'rgba(10,10,10,.35)';
x.fillRect(Math.round(px), 8, 1, major ? 16 : half ? 11 : 7);
if (major) x.fillText((i > 0 ? '+' : i < 0 ? '−' : '') + Math.abs(i / 10), px, 38);
}
}
function set(n) {
v = Math.round(Math.max(-3, Math.min(3, n)) * 10) / 10;
img.style.filter = 'brightness(' + Math.pow(2, v * .45).toFixed(3) + ') contrast(' + (1 + Math.abs(v) * .04).toFixed(3) + ')';
out.textContent = fmt(v) + ' EV';
ru.setAttribute('aria-valuenow', String(v)); ru.setAttribute('aria-valuetext', fmt(v) + ' EV');
draw();
}
ru.addEventListener('pointerdown', function (e) { dragging = true; x0 = e.clientX; v0 = v; ru.setPointerCapture(e.pointerId); });
ru.addEventListener('pointermove', function (e) { if (dragging) set(v0 - (e.clientX - x0) / (10 * STEP)); });
ru.addEventListener('pointerup', function () { dragging = false; }); ru.addEventListener('pointercancel', function () { dragging = false; });
ru.addEventListener('wheel', function (e) { e.preventDefault(); set(v + (e.deltaY + e.deltaX > 0 ? .1 : -.1)); }, { passive: false });
ru.addEventListener('keydown', function (e) { var k = e.key; if (k === 'ArrowRight' || k === 'ArrowUp') { e.preventDefault(); set(v + .1); } else if (k === 'ArrowLeft' || k === 'ArrowDown') { e.preventDefault(); set(v - .1); } else if (k === 'Home') set(-3); else if (k === 'End') set(3); else if (k === '0') set(0); });
ru.addEventListener('dblclick', function () { set(0); });
if ('ResizeObserver' in window) new ResizeObserver(draw).observe(ru);
if (document.fonts && document.fonts.ready) document.fonts.ready.then(draw);
set(0.7);
}
init(document.querySelector('.jouw-container'));
More forms & inputs
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →