51 lines
2.2 KiB
JavaScript
51 lines
2.2 KiB
JavaScript
// Inject the dots SVG layer into the Open WebUI DOM (chat theme companion script).
|
|
// Served as /static/coop-dots.js; kept minimal — no dependencies.
|
|
// With gentle parallax (12% scroll speed) matching the homepage.
|
|
(function () {
|
|
var NS = 'http://www.w3.org/2000/svg';
|
|
var svg = document.createElementNS(NS, 'svg');
|
|
svg.setAttribute('class', 'coop-dots');
|
|
svg.setAttribute('id', 'coop-dots-layer');
|
|
svg.setAttribute('aria-hidden', 'true');
|
|
var dots = [
|
|
// [cx%, cy%, r, fill, big]
|
|
[4, 12, 5, '#a8cdb4'], [12, 34, 4, '#b5d4c0'], [7, 58, 16, '#b7d8c2', 1],
|
|
[16, 78, 5, '#a8cdb4'], [24, 6, 9, '#b7d8c2'], [31, 22, 4, '#b5d4c0'],
|
|
[28, 52, 20, '#bfdccd', 1], [38, 70, 5, '#a8cdb4'], [47, 10, 6, '#b7d8c2'],
|
|
[55, 30, 24, '#bfdccd', 1], [52, 55, 4, '#a8cdb4'], [63, 14, 5, '#b5d4c0'],
|
|
[68, 42, 18, '#b7d8c2', 1], [61, 66, 6, '#bfdccd'], [72, 58, 4, '#b5d4c0'],
|
|
[78, 8, 8, '#a8cdb4'], [83, 26, 4, '#b5d4c0'], [76, 48, 6, '#bfdccd'],
|
|
[86, 38, 22, '#b7d8c2', 1], [93, 16, 5, '#a8cdb4'], [90, 60, 4, '#b5d4c0'],
|
|
[81, 72, 17, '#bfdccd', 1], [95, 46, 4, '#b5d4c0'], [89, 86, 5, '#a8cdb4'],
|
|
[9, 88, 16, '#b7d8c2', 1], [40, 88, 4, '#b5d4c0'], [57, 84, 5, '#a8cdb4'],
|
|
[70, 80, 18, '#bfdccd', 1],
|
|
[20, 44, 5, '#d9c3a8'], [44, 38, 4, '#e0cbb2'], [66, 30, 18, '#d9c3a8', 1],
|
|
[87, 70, 5, '#e0cbb2'], [33, 76, 4, '#d9c3a8'], [58, 72, 5, '#e0cbb2'],
|
|
[97, 78, 6, '#d9c3a8'], [3, 72, 4, '#e0cbb2']
|
|
];
|
|
dots.forEach(function (d) {
|
|
var c = document.createElementNS(NS, 'circle');
|
|
c.setAttribute('cx', d[0] + '%');
|
|
c.setAttribute('cy', d[1] + '%');
|
|
c.setAttribute('r', d[2]);
|
|
c.setAttribute('fill', d[3]);
|
|
if (d[4]) c.setAttribute('class', 'big');
|
|
svg.appendChild(c);
|
|
});
|
|
function mount() {
|
|
if (!document.body) { requestAnimationFrame(mount); return; }
|
|
document.body.insertBefore(svg, document.body.firstChild);
|
|
// gentle parallax
|
|
var ticking = false;
|
|
window.addEventListener('scroll', function () {
|
|
if (ticking) return;
|
|
ticking = true;
|
|
requestAnimationFrame(function () {
|
|
svg.style.transform = 'translateY(' + (window.scrollY * -0.12) + 'px)';
|
|
ticking = false;
|
|
});
|
|
}, { passive: true });
|
|
}
|
|
mount();
|
|
})();
|