File: /home/elrashedytravel/public_html/wp-content/themes/custom-functions-1767952375/js/dynamic-bg.js
// 动态背景生成器 - 仿照 Color Morph 效果
class DynamicBgGenerator {
constructor() {
this.svgNamespace = 'http://www.w3.org/2000/svg';
this.viewBoxWidth = 3000;
this.viewBoxHeight = 2000;
}
// 生成随机HSL颜色
generateRandomColor() {
const hue = Math.floor(Math.random() * 360);
const saturation = 85 + Math.random() * 10; // 85-95%
const lightness = 50 + Math.random() * 20; // 50-70%
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
}
// HSL转RGB
hslToRgb(hsl) {
const match = hsl.match(/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/);
if (!match) return 'rgba(0,0,0,1)';
let [, h, s, l] = match;
h = parseInt(h) / 360;
s = parseInt(s) / 100;
l = parseInt(l) / 100;
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
const r = Math.round(hue2rgb(p, q, h + 1/3) * 255);
const g = Math.round(hue2rgb(p, q, h) * 255);
const b = Math.round(hue2rgb(p, q, h - 1/3) * 255);
return `rgba(${r},${g},${b},1)`;
}
// 生成随机渐变位置
generateRandomPosition() {
return {
cx: Math.floor(Math.random() * 100) + '%',
cy: Math.floor(Math.random() * 100) + '%'
};
}
// 生成随机背景色
generateBackgroundColor() {
const darkHues = [240, 260, 280, 300, 320]; // 偏蓝紫色调
const hue = darkHues[Math.floor(Math.random() * darkHues.length)];
const saturation = 30 + Math.random() * 20; // 30-50%
const lightness = 10 + Math.random() * 15; // 10-25%
const hsl = `hsl(${hue}, ${saturation}%, ${lightness}%)`;
return this.hslToRgbHex(hsl);
}
// HSL转十六进制
hslToRgbHex(hsl) {
const match = hsl.match(/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/);
if (!match) return '#26004d';
let [, h, s, l] = match;
h = parseInt(h) / 360;
s = parseInt(s) / 100;
l = parseInt(l) / 100;
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
const r = Math.round(hue2rgb(p, q, h + 1/3) * 255);
const g = Math.round(hue2rgb(p, q, h) * 255);
const b = Math.round(hue2rgb(p, q, h - 1/3) * 255);
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
}
// 生成随机SVG背景
generateRandomSvg(layerCount = 7) {
const svg = document.createElementNS(this.svgNamespace, 'svg');
svg.setAttribute('viewBox', `0 0 ${this.viewBoxWidth} ${this.viewBoxHeight}`);
svg.setAttribute('fill', 'none');
svg.setAttribute('xmlns', this.svgNamespace);
const defs = document.createElementNS(this.svgNamespace, 'defs');
const gradients = [];
// 生成渐变定义
for (let i = 0; i < layerCount; i++) {
const gradient = document.createElementNS(this.svgNamespace, 'radialGradient');
const gradId = `grad${i}`;
const position = this.generateRandomPosition();
const color = this.hslToRgb(this.generateRandomColor());
gradient.setAttribute('id', gradId);
gradient.setAttribute('cx', position.cx);
gradient.setAttribute('cy', position.cy);
gradient.setAttribute('r', '100%');
gradient.setAttribute('fx', position.cx);
gradient.setAttribute('fy', position.cy);
gradient.setAttribute('gradientUnits', 'objectBoundingBox');
// 内部色彩停止点
const stop1 = document.createElementNS(this.svgNamespace, 'stop');
stop1.setAttribute('offset', '0');
stop1.setAttribute('stop-color', color);
stop1.setAttribute('stop-opacity', '1');
const stop2 = document.createElementNS(this.svgNamespace, 'stop');
stop2.setAttribute('offset', '0.5');
stop2.setAttribute('stop-color', color.replace('1)', '0)'));
stop2.setAttribute('stop-opacity', '0');
gradient.appendChild(stop1);
gradient.appendChild(stop2);
defs.appendChild(gradient);
gradients.push(gradId);
}
svg.appendChild(defs);
// 添加背景色矩形
const bgRect = document.createElementNS(this.svgNamespace, 'rect');
bgRect.setAttribute('x', '0');
bgRect.setAttribute('y', '0');
bgRect.setAttribute('width', this.viewBoxWidth.toString());
bgRect.setAttribute('height', this.viewBoxHeight.toString());
bgRect.setAttribute('fill', this.generateBackgroundColor());
svg.appendChild(bgRect);
// 添加渐变矩形
gradients.forEach(gradId => {
const rect = document.createElementNS(this.svgNamespace, 'rect');
rect.setAttribute('x', '0');
rect.setAttribute('y', '0');
rect.setAttribute('width', this.viewBoxWidth.toString());
rect.setAttribute('height', this.viewBoxHeight.toString());
rect.setAttribute('fill', `url(#${gradId})`);
svg.appendChild(rect);
});
return svg;
}
// 将SVG转换为Data URL
svgToDataUrl(svg) {
const serializer = new XMLSerializer();
const svgString = serializer.serializeToString(svg);
return `data:image/svg+xml;base64,${btoa(svgString)}`;
}
}
// 應用動態背景到文章卡片
function applyDynamicBackgrounds() {
const generator = new DynamicBgGenerator();
// 選擇所有沒有背景圖片樣式的post-card-image元素
const postCards = document.querySelectorAll('.post-card-image:not([style*="background-image"])');
postCards.forEach(card => {
// 移除靜態漸變類
card.classList.remove('gradient-1', 'gradient-2', 'gradient-3', 'gradient-4', 'gradient-5', 'dynamic-bg-placeholder');
// 生成並應用動態背景
const svg = generator.generateRandomSvg();
const dataUrl = generator.svgToDataUrl(svg);
card.style.backgroundImage = `url(${dataUrl})`;
card.style.backgroundSize = 'cover';
card.style.backgroundPosition = 'center';
// 添加標記類表示已處理
card.classList.add('dynamic-bg-applied');
});
console.log(`已為 ${postCards.length} 個文章卡片生成動態背景`);
}
// 页面加载完成后应用背景
document.addEventListener('DOMContentLoaded', applyDynamicBackgrounds);
// 如果需要在AJAX加载后重新应用背景
window.applyDynamicBackgrounds = applyDynamicBackgrounds;