From 72cf3dad986489b8f3993cde8d0f5ce0b80f4491 Mon Sep 17 00:00:00 2001 From: andre Date: Tue, 13 Oct 2026 18:57:21 +0100 Subject: [PATCH] feat(dev): lab - full grain controls (type, frequency, octaves, seed, contrast, softness, tile, blend, mono) + generated CSS Co-Authored-By: Claude Sonnet 5.5 --- lab.php | 103 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/lab.php b/lab.php index c3019dd..20f1a84 100644 --- a/lab.php +++ b/lab.php @@ -51,15 +51,16 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro @@ -88,6 +89,40 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro +

Textura do grão

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Passa o rato pelos botões, links, fotos, moldura e cartão para ver os efeitos. Os valores não são guardados.

@@ -153,11 +188,20 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro (function () { var root = document.documentElement, ov = document.getElementById('lab-overrides'); var $ = function (id) { return document.getElementById(id); }; - var DEF = { color: '#c2d500', btn: 16, head: 25, sat: 90, glow: 60, spin: 32, ring: 2 }; + var DEF = { color: '#c2d500', btn: 16, head: 25, sat: 90, glow: 60, spin: 32, ring: 2, + type: 'fractalNoise', freq: 90, oct: 2, seed: 4, contrast: 100, soft: 0, tile: 140, bbm: 'normal', hbm: 'multiply', mono: true }; var st = Object.assign({}, DEF); - function noiseUrl(op) { - return "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='" + op + "'/%3E%3C/svg%3E\")"; + function noiseUrl() { + var f = (st.freq / 100).toFixed(2), op = (st.btn / 100).toFixed(3), c = st.contrast / 100; + var svg = "" + + "" + + "" + + (st.mono ? "" : "") + + (st.soft > 0 ? "" : "") + + (c !== 1 ? "" : "") + + ""; + return 'url("data:image/svg+xml,' + svg.replace(//g, '%3E').replace(/#/g, '%23').replace(/%(?![0-9A-F]{2})/g, '%25') + '")'; } function brandVars(hex) { var r = parseInt(hex.slice(1, 3), 16), g = parseInt(hex.slice(3, 5), 16), b = parseInt(hex.slice(5, 7), 16); @@ -169,16 +213,30 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro function apply() { var v = brandVars(st.color); Object.keys(v).forEach(function (k) { root.style.setProperty(k, v[k]); }); - root.style.setProperty('--noise', noiseUrl((st.btn / 100).toFixed(3))); - var s = st.head / 100, slope = (s * .6).toFixed(3), icpt = (1 - s * .6).toFixed(3); + var url = noiseUrl(); + root.style.setProperty('--noise', url); + + // headings: the SVG filter + var s = st.head / 100, c = st.contrast / 100; + var slope = (s * .6 * c).toFixed(3), icpt = (1 - s * .6 * c / 2 - s * .6 * c / 2).toFixed(3); ['lab-fr', 'lab-fg', 'lab-fb'].forEach(function (id) { $(id).setAttribute('slope', slope); $(id).setAttribute('intercept', icpt); }); + $('lab-turb').setAttribute('type', st.type); + $('lab-turb').setAttribute('baseFrequency', (st.freq / 100).toFixed(2)); + $('lab-turb').setAttribute('numOctaves', st.oct); + $('lab-turb').setAttribute('seed', st.seed); + $('lab-sat').setAttribute('values', st.mono ? '0' : '1'); + $('lab-blur').setAttribute('stdDeviation', (st.soft / 10).toFixed(1)); + $('lab-blend').setAttribute('mode', st.hbm); + var glow = st.glow / 100, spin = (st.spin / 10).toFixed(1) + 's'; ov.textContent = + '.site-btn,.gym-switch-btn,.crossfit-nav-link { background-size: ' + st.tile + 'px ' + st.tile + 'px !important; background-blend-mode: ' + st.bbm + ' !important; }' + '.gal-link img, .trainer-item .trainer-pic img { filter: saturate(' + (st.sat / 100) + '); }' + '.gal-link:hover img, .trainer-item .trainer-pic:hover img { filter: saturate(1) brightness(1.05); }' + 'a:where(:not(.site-btn,.gym-switch-btn,.gal-link,.nav-link)):is(:hover,:focus-visible) { text-shadow: 0 0 10px rgba(var(--fitme-accent-rgb),' + (.6 * glow * 1.67).toFixed(2) + '), 0 0 22px rgba(var(--fitme-accent-rgb),' + (.3 * glow * 1.67).toFixed(2) + ') !important; }' + '.site-btn::before,.site-btn::after,.gym-switch-btn::before,.gym-switch-btn::after,.price-card::before,.price-card::after,.gal-link::after,.icon-box-item .ib-icon::after,.trainer-item .trainer-pic:hover { animation-duration: ' + spin + ' !important; }' + '.site-btn,.gym-switch-btn { --ring: ' + st.ring + 'px; }'; + $('o-color').textContent = st.color.toUpperCase(); $('o-btn').textContent = st.btn + '%'; $('o-head').textContent = st.head + '%'; @@ -186,14 +244,35 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro $('o-glow').textContent = st.glow + '%'; $('o-spin').textContent = spin; $('o-ring').textContent = st.ring; + $('o-freq').textContent = (st.freq / 100).toFixed(2); + $('o-oct').textContent = st.oct; + $('o-seed').textContent = st.seed; + $('o-contrast').textContent = st.contrast + '%'; + $('o-soft').textContent = (st.soft / 10).toFixed(1); + $('o-tile').textContent = st.tile; + + $('c-css').value = + ':root {\n --noise: ' + url + ';\n}\n' + + '.site-btn, .gym-switch-btn, .crossfit-nav-link {\n background-image: var(--noise) !important;\n background-size: ' + st.tile + 'px ' + st.tile + 'px !important;' + + (st.bbm !== 'normal' ? '\n background-blend-mode: ' + st.bbm + ' !important;' : '') + '\n}\n' + + '/* títulos: */\n' + + 'feTurbulence type="' + st.type + '" baseFrequency="' + (st.freq / 100).toFixed(2) + '" numOctaves="' + st.oct + '" seed="' + st.seed + '"\n' + + 'feColorMatrix saturate ' + (st.mono ? 0 : 1) + ' · feGaussianBlur ' + (st.soft / 10).toFixed(1) + '\n' + + 'feFunc* slope="' + slope + '" intercept="' + icpt + '" · feBlend mode="' + st.hbm + '"'; } - var map = { 'c-color': 'color', 'c-btn': 'btn', 'c-head': 'head', 'c-sat': 'sat', 'c-glow': 'glow', 'c-spin': 'spin', 'c-ring': 'ring' }; + var map = { 'c-color': 'color', 'c-btn': 'btn', 'c-head': 'head', 'c-sat': 'sat', 'c-glow': 'glow', 'c-spin': 'spin', 'c-ring': 'ring', + 'c-type': 'type', 'c-freq': 'freq', 'c-oct': 'oct', 'c-seed': 'seed', 'c-contrast': 'contrast', 'c-soft': 'soft', 'c-tile': 'tile', + 'c-bbm': 'bbm', 'c-hbm': 'hbm', 'c-mono': 'mono' }; + var textual = { 'c-color': 1, 'c-type': 1, 'c-bbm': 1, 'c-hbm': 1 }; Object.keys(map).forEach(function (id) { - $(id).addEventListener('input', function () { st[map[id]] = id === 'c-color' ? this.value : +this.value; apply(); }); + $(id).addEventListener('input', function () { + st[map[id]] = id === 'c-mono' ? this.checked : (textual[id] ? this.value : +this.value); + apply(); + }); }); $('c-reset').addEventListener('click', function () { st = Object.assign({}, DEF); - Object.keys(map).forEach(function (id) { $(id).value = DEF[map[id]]; }); + Object.keys(map).forEach(function (id) { if (id === 'c-mono') $(id).checked = DEF.mono; else $(id).value = DEF[map[id]]; }); apply(); }); apply();