feat(dev): lab - full grain controls (type, frequency, octaves, seed, contrast, softness, tile, blend, mono) + generated CSS
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e5f4fd8fc9
commit
72cf3dad98
1 file changed
+91
-12
@@ -51,15 +51,16 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro
|
|||||||
<?php include __DIR__ . '/includes/env_ribbon.php'; ?>
|
<?php include __DIR__ . '/includes/env_ribbon.php'; ?>
|
||||||
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
|
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
|
||||||
<filter id="pt-noise" x="0" y="0" width="100%" height="100%" color-interpolation-filters="sRGB">
|
<filter id="pt-noise" x="0" y="0" width="100%" height="100%" color-interpolation-filters="sRGB">
|
||||||
<feTurbulence type="fractalNoise" baseFrequency=".9" numOctaves="2" seed="4" result="n"/>
|
<feTurbulence id="lab-turb" type="fractalNoise" baseFrequency=".9" numOctaves="2" seed="4" result="n"/>
|
||||||
<feColorMatrix in="n" type="saturate" values="0" result="g"/>
|
<feColorMatrix id="lab-sat" in="n" type="saturate" values="0" result="g"/>
|
||||||
<feComponentTransfer in="g" result="grain">
|
<feGaussianBlur id="lab-blur" in="g" stdDeviation="0" result="gb"/>
|
||||||
|
<feComponentTransfer in="gb" result="grain">
|
||||||
<feFuncR id="lab-fr" type="linear" slope=".15" intercept=".86"/>
|
<feFuncR id="lab-fr" type="linear" slope=".15" intercept=".86"/>
|
||||||
<feFuncG id="lab-fg" type="linear" slope=".15" intercept=".86"/>
|
<feFuncG id="lab-fg" type="linear" slope=".15" intercept=".86"/>
|
||||||
<feFuncB id="lab-fb" type="linear" slope=".15" intercept=".86"/>
|
<feFuncB id="lab-fb" type="linear" slope=".15" intercept=".86"/>
|
||||||
<feFuncA type="linear" slope="0" intercept="1"/>
|
<feFuncA type="linear" slope="0" intercept="1"/>
|
||||||
</feComponentTransfer>
|
</feComponentTransfer>
|
||||||
<feBlend in="SourceGraphic" in2="grain" mode="multiply" result="mix"/>
|
<feBlend id="lab-blend" in="SourceGraphic" in2="grain" mode="multiply" result="mix"/>
|
||||||
<feComposite in="mix" in2="SourceGraphic" operator="in"/>
|
<feComposite in="mix" in2="SourceGraphic" operator="in"/>
|
||||||
</filter>
|
</filter>
|
||||||
</svg>
|
</svg>
|
||||||
@@ -88,6 +89,40 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro
|
|||||||
<label for="c-ring">Espessura da aresta (px) <output id="o-ring"></output></label>
|
<label for="c-ring">Espessura da aresta (px) <output id="o-ring"></output></label>
|
||||||
<input type="range" id="c-ring" min="1" max="6" value="2">
|
<input type="range" id="c-ring" min="1" max="6" value="2">
|
||||||
|
|
||||||
|
<h2 style="margin-top:18px">Textura do grão</h2>
|
||||||
|
|
||||||
|
<label for="c-type">Tipo</label>
|
||||||
|
<select id="c-type" class="form-select form-select-sm"><option value="fractalNoise">Fino (fractalNoise)</option><option value="turbulence">Manchado (turbulence)</option></select>
|
||||||
|
|
||||||
|
<label for="c-freq">Tamanho do grão (frequência) <output id="o-freq"></output></label>
|
||||||
|
<input type="range" id="c-freq" min="5" max="200" value="90">
|
||||||
|
|
||||||
|
<label for="c-oct">Detalhe (oitavas) <output id="o-oct"></output></label>
|
||||||
|
<input type="range" id="c-oct" min="1" max="5" value="2">
|
||||||
|
|
||||||
|
<label for="c-seed">Semente <output id="o-seed"></output></label>
|
||||||
|
<input type="range" id="c-seed" min="0" max="50" value="4">
|
||||||
|
|
||||||
|
<label for="c-contrast">Contraste do grão <output id="o-contrast"></output></label>
|
||||||
|
<input type="range" id="c-contrast" min="20" max="250" value="100">
|
||||||
|
|
||||||
|
<label for="c-soft">Suavidade (desfoque) <output id="o-soft"></output></label>
|
||||||
|
<input type="range" id="c-soft" min="0" max="20" value="0">
|
||||||
|
|
||||||
|
<label for="c-tile">Mosaico dos botões (px) <output id="o-tile"></output></label>
|
||||||
|
<input type="range" id="c-tile" min="40" max="400" value="140">
|
||||||
|
|
||||||
|
<label for="c-bbm">Mistura nos botões</label>
|
||||||
|
<select id="c-bbm" class="form-select form-select-sm"><option>normal</option><option>multiply</option><option>overlay</option><option>soft-light</option><option>hard-light</option><option>screen</option><option>darken</option><option>lighten</option></select>
|
||||||
|
|
||||||
|
<label for="c-hbm">Mistura nos títulos</label>
|
||||||
|
<select id="c-hbm" class="form-select form-select-sm"><option>multiply</option><option>overlay</option><option>soft-light</option><option>screen</option><option>darken</option><option>lighten</option></select>
|
||||||
|
|
||||||
|
<label style="justify-content:flex-start;align-items:center"><input type="checkbox" id="c-mono" checked> Só cinzento (sem cor no grão)</label>
|
||||||
|
|
||||||
|
<label for="c-css">CSS gerado (copiar)</label>
|
||||||
|
<textarea id="c-css" class="form-control form-control-sm" rows="9" readonly style="font-family:monospace;font-size:.7rem"></textarea>
|
||||||
|
|
||||||
<button type="button" class="reset" id="c-reset">Repor valores</button>
|
<button type="button" class="reset" id="c-reset">Repor valores</button>
|
||||||
<p class="hint">Passa o rato pelos botões, links, fotos, moldura e cartão para ver os efeitos. Os valores não são guardados.</p>
|
<p class="hint">Passa o rato pelos botões, links, fotos, moldura e cartão para ver os efeitos. Os valores não são guardados.</p>
|
||||||
</aside>
|
</aside>
|
||||||
@@ -153,11 +188,20 @@ $img_gal = [base_url('site/assets/img/home.jpg'), base_url('site/assets/img/cro
|
|||||||
(function () {
|
(function () {
|
||||||
var root = document.documentElement, ov = document.getElementById('lab-overrides');
|
var root = document.documentElement, ov = document.getElementById('lab-overrides');
|
||||||
var $ = function (id) { return document.getElementById(id); };
|
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);
|
var st = Object.assign({}, DEF);
|
||||||
|
|
||||||
function noiseUrl(op) {
|
function noiseUrl() {
|
||||||
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\")";
|
var f = (st.freq / 100).toFixed(2), op = (st.btn / 100).toFixed(3), c = st.contrast / 100;
|
||||||
|
var svg = "<svg xmlns='http://www.w3.org/2000/svg' width='" + st.tile + "' height='" + st.tile + "'>" +
|
||||||
|
"<filter id='n' x='0' y='0' width='100%' height='100%'>" +
|
||||||
|
"<feTurbulence type='" + st.type + "' baseFrequency='" + f + "' numOctaves='" + st.oct + "' seed='" + st.seed + "' stitchTiles='stitch'/>" +
|
||||||
|
(st.mono ? "<feColorMatrix type='saturate' values='0'/>" : "") +
|
||||||
|
(st.soft > 0 ? "<feGaussianBlur stdDeviation='" + (st.soft / 10).toFixed(1) + "'/>" : "") +
|
||||||
|
(c !== 1 ? "<feComponentTransfer><feFuncR type='linear' slope='" + c + "' intercept='" + ((1 - c) / 2).toFixed(3) + "'/><feFuncG type='linear' slope='" + c + "' intercept='" + ((1 - c) / 2).toFixed(3) + "'/><feFuncB type='linear' slope='" + c + "' intercept='" + ((1 - c) / 2).toFixed(3) + "'/></feComponentTransfer>" : "") +
|
||||||
|
"</filter><rect width='100%' height='100%' filter='url(#n)' opacity='" + op + "'/></svg>";
|
||||||
|
return 'url("data:image/svg+xml,' + svg.replace(/</g, '%3C').replace(/>/g, '%3E').replace(/#/g, '%23').replace(/%(?![0-9A-F]{2})/g, '%25') + '")';
|
||||||
}
|
}
|
||||||
function brandVars(hex) {
|
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);
|
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() {
|
function apply() {
|
||||||
var v = brandVars(st.color);
|
var v = brandVars(st.color);
|
||||||
Object.keys(v).forEach(function (k) { root.style.setProperty(k, v[k]); });
|
Object.keys(v).forEach(function (k) { root.style.setProperty(k, v[k]); });
|
||||||
root.style.setProperty('--noise', noiseUrl((st.btn / 100).toFixed(3)));
|
var url = noiseUrl();
|
||||||
var s = st.head / 100, slope = (s * .6).toFixed(3), icpt = (1 - s * .6).toFixed(3);
|
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-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';
|
var glow = st.glow / 100, spin = (st.spin / 10).toFixed(1) + 's';
|
||||||
ov.textContent =
|
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 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); }' +
|
'.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; }' +
|
'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::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; }';
|
'.site-btn,.gym-switch-btn { --ring: ' + st.ring + 'px; }';
|
||||||
|
|
||||||
$('o-color').textContent = st.color.toUpperCase();
|
$('o-color').textContent = st.color.toUpperCase();
|
||||||
$('o-btn').textContent = st.btn + '%';
|
$('o-btn').textContent = st.btn + '%';
|
||||||
$('o-head').textContent = st.head + '%';
|
$('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-glow').textContent = st.glow + '%';
|
||||||
$('o-spin').textContent = spin;
|
$('o-spin').textContent = spin;
|
||||||
$('o-ring').textContent = st.ring;
|
$('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: <filter id="pt-noise"> */\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) {
|
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 () {
|
$('c-reset').addEventListener('click', function () {
|
||||||
st = Object.assign({}, DEF);
|
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();
|
||||||
});
|
});
|
||||||
apply();
|
apply();
|
||||||
|
|||||||
Reference in new issue
Block a user