mirror of
https://gitlab.com/vyla-entertainment/documentation.git
synced 2026-11-12 13:37:20 -05:00
133 lines
6.6 KiB
JavaScript
133 lines
6.6 KiB
JavaScript
var GLASS_TARGETS = [
|
|
{
|
|
selector: ".btn-primary",
|
|
options: {
|
|
distortionScale: -300,
|
|
displace: 0,
|
|
backgroundOpacity: 0.1
|
|
}
|
|
},
|
|
{
|
|
selector: ".btn-secondary",
|
|
options: {
|
|
distortionScale: -300,
|
|
displace: 0,
|
|
backgroundOpacity: 0.1
|
|
}
|
|
},
|
|
{
|
|
selector: ".hero-greeting",
|
|
options: {
|
|
distortionScale: -200,
|
|
displace: 0,
|
|
backgroundOpacity: 0.08
|
|
}
|
|
},
|
|
{
|
|
selector: ".feature-box",
|
|
options: {
|
|
distortionScale: -220,
|
|
displace: 0,
|
|
backgroundOpacity: 0.12,
|
|
saturation: 1.3,
|
|
cornerRadius: 30
|
|
}
|
|
}
|
|
];
|
|
|
|
function initGlassSurface(el, opts) {
|
|
if (!el || el.getAttribute("data-glass")) return;
|
|
el.setAttribute("data-glass", "true");
|
|
opts = opts || {};
|
|
var distortionScale = opts.distortionScale !== undefined ? opts.distortionScale : -180;
|
|
var displace = opts.displace !== undefined ? opts.displace : 0;
|
|
var backgroundOpacity = opts.backgroundOpacity !== undefined ? opts.backgroundOpacity : 0;
|
|
var saturation = opts.saturation !== undefined ? opts.saturation : 1;
|
|
var redOffset = opts.redOffset !== undefined ? opts.redOffset : 0;
|
|
var greenOffset = opts.greenOffset !== undefined ? opts.greenOffset : 10;
|
|
var blueOffset = opts.blueOffset !== undefined ? opts.blueOffset : 20;
|
|
var borderWidth = opts.borderWidth !== undefined ? opts.borderWidth : 0.07;
|
|
var brightness = opts.brightness !== undefined ? opts.brightness : 50;
|
|
var opacity = opts.opacity !== undefined ? opts.opacity : 0.93;
|
|
var blur = opts.blur !== undefined ? opts.blur : 11;
|
|
var mixBlendMode = opts.mixBlendMode || "difference";
|
|
|
|
var uid = Math.random().toString(36).slice(2, 9);
|
|
var filterId = "glass-filter-" + uid;
|
|
var redGradId = "red-grad-" + uid;
|
|
var blueGradId = "blue-grad-" + uid;
|
|
var softId = "soft-" + uid;
|
|
|
|
var isWebkit = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
|
|
var isFirefox = /Firefox/.test(navigator.userAgent);
|
|
var div = document.createElement("div");
|
|
div.style.backdropFilter = "url(#" + filterId + ")";
|
|
var svgSupported = !isWebkit && !isFirefox && div.style.backdropFilter !== "";
|
|
|
|
var rect = el.getBoundingClientRect();
|
|
var w = Math.round(rect.width) || 160;
|
|
var h = Math.round(rect.height) || 40;
|
|
var r = opts.cornerRadius !== undefined ? opts.cornerRadius : Math.round(h / 2);
|
|
var edge = Math.min(w, h) * (borderWidth * 0.5);
|
|
|
|
var mapSvg = '<svg width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '" xmlns="http://www.w3.org/2000/svg">' +
|
|
'<defs>' +
|
|
'<linearGradient id="' + redGradId + '" x1="100%" y1="0%" x2="0%" y2="0%"><stop offset="0%" stop-color="#0000"/><stop offset="100%" stop-color="red"/></linearGradient>' +
|
|
'<linearGradient id="' + blueGradId + '" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#0000"/><stop offset="100%" stop-color="blue"/></linearGradient>' +
|
|
'<filter id="' + softId + '" filterUnits="userSpaceOnUse" x="0" y="0" width="' + w + '" height="' + h + '" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="' + blur + '"/></filter>' +
|
|
'</defs>' +
|
|
'<rect x="0" y="0" width="' + w + '" height="' + h + '" fill="black"/>' +
|
|
'<rect x="0" y="0" width="' + w + '" height="' + h + '" rx="' + r + '" fill="url(#' + redGradId + ')"/>' +
|
|
'<rect x="0" y="0" width="' + w + '" height="' + h + '" rx="' + r + '" fill="url(#' + blueGradId + ')" style="mix-blend-mode:' + mixBlendMode + '"/>' +
|
|
'<rect x="' + edge + '" y="' + edge + '" width="' + (w - edge * 2) + '" height="' + (h - edge * 2) + '" rx="' + r + '" fill="hsl(0 0% ' + brightness + '% / ' + opacity + ')" filter="url(#' + softId + ')"/>' +
|
|
'</svg>';
|
|
var mapUrl = "data:image/svg+xml," + encodeURIComponent(mapSvg);
|
|
|
|
el.style.setProperty("--glass-frost", backgroundOpacity);
|
|
el.style.setProperty("--glass-saturation", saturation);
|
|
el.style.setProperty("--filter-id", "url(#" + filterId + ")");
|
|
el.classList.add(svgSupported ? "glass-surface--svg" : "glass-surface--fallback");
|
|
|
|
var filterSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
filterSvg.setAttribute("class", "glass-surface__filter");
|
|
filterSvg.innerHTML = '<defs>' +
|
|
'<filter id="' + filterId + '" color-interpolation-filters="sRGB" x="0%" y="0%" width="100%" height="100%">' +
|
|
'<feImage href="' + mapUrl + '" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none" result="map"/>' +
|
|
'<feDisplacementMap in="SourceGraphic" in2="map" scale="' + (distortionScale + redOffset) + '" xChannelSelector="R" yChannelSelector="G" result="dispRed"/>' +
|
|
'<feColorMatrix in="dispRed" type="matrix" values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" result="red"/>' +
|
|
'<feDisplacementMap in="SourceGraphic" in2="map" scale="' + (distortionScale + greenOffset) + '" xChannelSelector="R" yChannelSelector="G" result="dispGreen"/>' +
|
|
'<feColorMatrix in="dispGreen" type="matrix" values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0" result="green"/>' +
|
|
'<feDisplacementMap in="SourceGraphic" in2="map" scale="' + (distortionScale + blueOffset) + '" xChannelSelector="R" yChannelSelector="G" result="dispBlue"/>' +
|
|
'<feColorMatrix in="dispBlue" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0" result="blue"/>' +
|
|
'<feBlend in="red" in2="green" mode="screen" result="rg"/>' +
|
|
'<feBlend in="rg" in2="blue" mode="screen" result="output"/>' +
|
|
'<feGaussianBlur in="output" stdDeviation="' + (displace || 0.7) + '"/>' +
|
|
'</filter></defs>';
|
|
|
|
var childNodes = Array.prototype.slice.call(el.childNodes);
|
|
var wrap = document.createElement("div");
|
|
wrap.className = "glass-surface__content";
|
|
childNodes.forEach(function (n) { wrap.appendChild(n); });
|
|
|
|
el.appendChild(filterSvg);
|
|
if (!svgSupported) {
|
|
var sheen = document.createElement("span");
|
|
sheen.className = "glass-surface__sheen";
|
|
sheen.setAttribute("aria-hidden", "true");
|
|
var rim = document.createElement("span");
|
|
rim.className = "glass-surface__rim";
|
|
rim.setAttribute("aria-hidden", "true");
|
|
el.appendChild(sheen);
|
|
el.appendChild(rim);
|
|
}
|
|
el.appendChild(wrap);
|
|
}
|
|
|
|
function applyGlassSurfaces(root) {
|
|
var base = root || document;
|
|
GLASS_TARGETS.forEach(function (target) {
|
|
base.querySelectorAll(target.selector).forEach(function (el) {
|
|
initGlassSurface(el, target.options);
|
|
});
|
|
});
|
|
} |