xBlog 背景相关代码
作者: iTxGo |
发布于: 2026-01-18 10:51 |
更新于: 2026-01-21 21:19 |
分类: 笔记 |
浏览: 243 |
简约平替版:
第一步:CSS 代码 - 粘贴到 style.css 文件中
/* ==========================================
动态背景
========================================== */
.bg-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
overflow: hidden;
filter: blur(380px) contrast(120%);
background-color: #FDFFF0;
}
.fluid-shape {
position: absolute;
top: 0;
left: 0;
border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%; /* 初始不规则形状 */
opacity: 0.95;
will-change: transform;
animation: drift linear infinite;
}
/* 飘动动画 */
@keyframes drift {
0% { transform: translate(0, 0) rotate(0deg) scale(1); }
25% { transform: translate(50px, -50px) rotate(90deg) scale(1.1); }
50% { transform: translate(0, 50px) rotate(180deg) scale(0.9); }
75% { transform: translate(-50px, 0) rotate(270deg) scale(1.05); }
100% { transform: translate(0, 0) rotate(360deg) scale(1); }
}
/* 形状变形动画 */
@keyframes morph {
0% { border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%; }
33% { border-radius: 70% 30% 30% 70% / 60% 40% 60% 40%; }
66% { border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; }
100% { border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%; }
}
第二步:HTML 代码 - 粘贴到 header.php <body> 最上方
<!-- 动态背景容器 -->
<div class="bg-container" id="bgContainer"></div>
第三步:JavaScript 代码 - 粘贴到 header.php </body> 标签之前
<!-- 动态背景容器 -->
<script>
document.addEventListener('DOMContentLoaded', () => {
const container = document.getElementById('bgContainer');
const colors = ['#86DFE9', '#A4EFF4', '#FDFFF0', '#D6F2C7'];
const shapeCount = 8; // 生成多少个色块,可以改这个数字
for (let i = 0; i < shapeCount; i++) {
createShape();
}
function createShape() {
const div = document.createElement('div');
div.classList.add('fluid-shape');
// 1. 随机大小 (30vw 到 60vw 之间)
const size = Math.random() * 30 + 180;
div.style.width = `${size}vw`;
div.style.height = `${size}vw`;
// 2. 随机颜色
div.style.background = colors[Math.floor(Math.random() * colors.length)];
// 3. 随机位置 (-10% 到 100% 之间,确保能飘进屏幕)
const posX = Math.random() * 110 - 10;
const posY = Math.random() * 110 - 10;
div.style.left = `${posX}%`;
div.style.top = `${posY}%`;
// 4. 随机动画时长 (20s 到 40s),让速度不一样
const duration = Math.random() * 20 + 20;
div.style.animationDuration = `${duration}s, ${duration}s`; // 同时应用到 drift 和 morph
// 5. 应用变形动画
// 注意:这里我们给它添加第二个动画效果 'morph'
div.style.animationName = 'drift, morph';
container.appendChild(div);
}
});
</script>
织物质感背景
/* 织物质感背景 */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(46, 164, 79, 0.05) 2px, /* 0.1 */
rgba(46, 164, 79, 0.05) 4px /* 0.1 */
),
repeating-linear-gradient(
90deg,
transparent,
transparent 2px,
rgba(46, 164, 79, 0.03) 2px, /* 0.08 */
rgba(46, 164, 79, 0.03) 4px /* 0.08 */
);
background-size: 40px 40px;
z-index: -1;
pointer-events: none;
opacity: 0.6;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body::before {
background:
repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(46, 164, 79, 0.08) 2px,
rgba(46, 164, 79, 0.08) 4px
),
repeating-linear-gradient(
90deg,
transparent,
transparent 2px,
rgba(46, 164, 79, 0.05) 2px,
rgba(46, 164, 79, 0.05) 4px
);
opacity: 0.4;
}
}
/* 移动端优化 */
@media (max-width: 768px) {
body::before {
background-size: 60px 60px;
opacity: 0.4;
}
}
现代噪点纸质感
/* 现代噪点纸质感 */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 使用SVG生成噪点纹理,无需外部图片 */
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='0.08'/%3E%3C/svg%3E");
background-color: #f9f9f9; /* 极淡的暖灰底色 */
z-index: -1;
pointer-events: none;
opacity: 1;
}
@media (prefers-color-scheme: dark) {
body::before {
background-color: #1a1a1a; /* 深灰底色 */
/* 深色模式下噪点稍微亮一点,增加层次 */
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='0.1'/%3E%3C/svg%3E");
}
}
@media (max-width: 768px) {
body::before {
/* 移动端稍微减少噪点密度,看起来更干净 */
background-size: 150px 150px;
}
}
极简几何点阵
/* 极简几何点阵 */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #f8fafc; /* 极淡的冷灰色 */
background-image: radial-gradient(#94a3b8 1px, transparent 1px);
background-size: 30px 30px; /* 点之间的间距 */
z-index: -1;
pointer-events: none;
opacity: 1;
}
@media (prefers-color-scheme: dark) {
body::before {
background-color: #0f172a; /* 深蓝灰底色 */
background-image: radial-gradient(#334155 1px, transparent 1px); /* 深色的点 */
}
}
@media (max-width: 768px) {
body::before {
/* 移动端把点阵放大,减少视觉噪音 */
background-size: 40px 40px;
}
}
极光弥散背景
/* 极光弥散背景 */
body {
background-color: #f8fafc; /* 浅色模式底色 */
}
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 四角柔和光斑:紫、蓝、粉、靛 */
background-image:
radial-gradient(at 0% 0%, rgba(192, 132, 252, 0.15) 0px, transparent 50%),
radial-gradient(at 100% 0%, rgba(96, 165, 250, 0.15) 0px, transparent 50%),
radial-gradient(at 0% 100%, rgba(244, 114, 182, 0.15) 0px, transparent 50%),
radial-gradient(at 100% 100%, rgba(129, 140, 248, 0.15) 0px, transparent 50%);
filter: blur(40px); /* 关键:高斯模糊制造弥散感 */
z-index: -1;
pointer-events: none;
opacity: 0.8;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body {
background-color: #0f172a; /* 深色模式底色 */
}
body::before {
/* 深色模式下加深颜色,模拟发光 */
background-image:
radial-gradient(at 0% 0%, rgba(139, 92, 246, 0.25) 0px, transparent 50%),
radial-gradient(at 100% 0%, rgba(56, 189, 248, 0.25) 0px, transparent 50%),
radial-gradient(at 0% 100%, rgba(236, 72, 153, 0.2) 0px, transparent 50%),
radial-gradient(at 100% 100%, rgba(99, 102, 241, 0.2) 0px, transparent 50%);
filter: blur(60px); /* 模糊范围更大 */
opacity: 0.6;
}
}
/* 移动端优化 */
@media (max-width: 768px) {
body::before {
filter: blur(30px); /* 减少模糊以提升移动端性能 */
opacity: 0.6;
}
}
NodeSeek 背景
<body class="grid-bg">
<!-- 页面内容 -->
</body>
/* 基础方格背景(浅色模式) */
.grid-bg {
background-color: #fffcf8;
background-image:
linear-gradient(#d4d4d4 1px, transparent 1px),
linear-gradient(90deg, #d4d4d4 1px, transparent 1px);
background-size: 32px 32px;
}
/* 深色模式 */
.dark-mode .grid-bg {
background-color: #272727;
background-image:
linear-gradient(#555 1px, transparent 1px),
linear-gradient(90deg, #555 1px, transparent 1px);
background-size: 32px 32px;
}
/* 菱形背景(可选) */
.grid-diamond {
background-color: #fff;
background-image:
linear-gradient(135deg, #d4d4d4 25%, transparent 25%),
linear-gradient(225deg, #d4d4d4 25%, transparent 25%),
linear-gradient(45deg, #d4d4d4 25%, transparent 25%),
linear-gradient(315deg, #d4d4d4 25%, #f5f5f5 25%);
background-position: 0 0, 0 0, 32px 32px, 32px 32px;
background-size: 64px 64px;
}
菱形背景
/* 菱形背景 */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(52, 168, 83, 0.04) 10px,
rgba(52, 168, 83, 0.04) 20px
),
repeating-linear-gradient(
-45deg,
transparent,
transparent 10px,
rgba(66, 133, 244, 0.03) 10px,
rgba(66, 133, 244, 0.03) 20px
);
background-size: 100% 100%;
z-index: -1;
pointer-events: none;
opacity: 0.6;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body::before {
background:
repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(52, 168, 83, 0.06) 10px,
rgba(52, 168, 83, 0.06) 20px
),
repeating-linear-gradient(
-45deg,
transparent,
transparent 15px,
rgba(66, 133, 244, 0.04) 15px,
rgba(66, 133, 244, 0.04) 30px
);
opacity: 0.4;
}
}
/* 移动端优化 */
@media (max-width: 768px) {
body::before {
opacity: 0.4;
}
}
水彩晕染背景
/* 水彩晕染背景 */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(ellipse at 20% 20%, rgba(137, 196, 244, 0.15) 0%, transparent 40%),
radial-gradient(ellipse at 80% 80%, rgba(244, 137, 235, 0.12) 0%, transparent 40%),
radial-gradient(ellipse at 40% 60%, rgba(137, 244, 195, 0.1) 0%, transparent 40%),
radial-gradient(ellipse at 60% 20%, rgba(244, 194, 137, 0.1) 0%, transparent 40%);
background-blend-mode: overlay;
filter: blur(2px);
z-index: -1;
pointer-events: none;
opacity: 0.8;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body::before {
background:
radial-gradient(ellipse at 20% 20%, rgba(100, 150, 220, 0.2) 0%, transparent 40%),
radial-gradient(ellipse at 80% 80%, rgba(220, 100, 200, 0.15) 0%, transparent 40%),
radial-gradient(ellipse at 40% 60%, rgba(100, 220, 150, 0.15) 0%, transparent 40%);
filter: blur(3px);
opacity: 0.4;
}
}
/* 移动端优化 */
@media (max-width: 768px) {
body::before {
filter: blur(1px);
opacity: 0.5;
}
}
霓虹渐变背景
/* 霓虹渐变背景 */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(
ellipse at center,
#00ff88 0%,
transparent 90%
),
radial-gradient(
ellipse at 80% 20%,
#ff0055 0%,
transparent 70%
);
background-blend-mode: screen;
filter: contrast(300%) brightness(150%);
z-index: -1;
pointer-events: none;
opacity: 0.3;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body::before {
background:
radial-gradient(
ellipse at center,
#00ff88 0%,
transparent 80%
),
radial-gradient(
ellipse at 20% 80%,
#ff0055 0%,
transparent 60%
);
filter: contrast(400%) brightness(200%);
opacity: 0.6;
mix-blend-mode: overlay;
}
}
/* 移动端优化 */
@media (max-width: 768px) {
body::before {
filter: contrast(200%) brightness(120%);
opacity: 0.6;
}
}
颗粒质感霓虹渐变背景
/* 颗粒质感霓虹渐变 */
body::before {
content: '';
position: fixed;
top: -50%;
left: -50%;
width: 220%;
height: 220%;
background:
radial-gradient(
ellipse at center,
#00ff88 0%,
transparent 60%
),
radial-gradient(
ellipse at 50% 40%,
#ff0044 0%,
transparent 40%
);
background-blend-mode: screen;
filter: contrast(300%) brightness(150%);
z-index: -1;
pointer-events: none;
opacity: 0.35;
animation: rotateAndShift 8s ease-in-out infinite;
}
/* 静态颗粒纹理层 */
body::after {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
opacity: 1;
mix-blend-mode: overlay;
}
/* 旋转和位移动画 */
@keyframes rotateAndShift {
0%, 100% {
transform: translate(0, 0) rotate(0deg);
filter: contrast(300%) brightness(150%) hue-rotate(0deg);
}
25% {
transform: translate(5%, -5%) rotate(5deg);
filter: contrast(320%) brightness(160%) hue-rotate(15deg);
}
50% {
transform: translate(-5%, 5%) rotate(-5deg);
filter: contrast(340%) brightness(170%) hue-rotate(30deg);
}
75% {
transform: translate(3%, 3%) rotate(3deg);
filter: contrast(320%) brightness(160%) hue-rotate(15deg);
}
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body::before {
background:
radial-gradient(
ellipse at center,
#00ff88 0%,
transparent 80%
),
radial-gradient(
ellipse at 20% 80%,
#ff0055 0%,
transparent 60%
);
filter: contrast(400%) brightness(200%);
opacity: 0.6;
mix-blend-mode: overlay;
animation: rotateAndShift 6s ease-in-out infinite;
}
/* 深色模式增强颗粒对比度 */
body::after {
opacity: 0.12;
mix-blend-mode: soft-light;
}
}
/* 移动端优化 */
@media (max-width: 768px) {
body::before {
filter: contrast(200%) brightness(120%);
opacity: 0.6;
animation: rotateAndShift 10s ease-in-out infinite;
}
}
✅️延迟版颗粒质感霓虹渐变背景
/* ==========================================
颗粒质感霓虹延迟渐变背景
========================================== */
/* 背景伪元素容器 */
body::before,
body::after {
content: '';
position: fixed;
z-index: -1;
pointer-events: none;
opacity: 0;
}
/* 主渐变层:霓虹色彩混合 */
body::before {
top: -50%;
left: -50%;
width: 220%;
height: 220%;
background:
radial-gradient(ellipse at center, #00ff88 0%, transparent 60%),
radial-gradient(ellipse at 50% 40%, #ff0044 0%, transparent 40%);
background-blend-mode: screen;
filter: contrast(300%) brightness(150%);
animation:
fadeInBackground 1.2s ease-out 0.2s forwards,
rotateAndShift 8s ease-in-out 1.4s infinite;
}
/* 噪点纹理层:增加颗粒质感 */
body::after {
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
mix-blend-mode: overlay;
animation: fadeInNoise 1.2s ease-out 0.2s forwards;
}
/* 渐显动画 */
@keyframes fadeInBackground {
to { opacity: 0.35; }
}
@keyframes fadeInNoise {
to { opacity: 1; }
}
/* 动态旋转位移动画 */
@keyframes rotateAndShift {
0%, 100% {
transform: translate(0, 0) rotate(0deg);
filter: contrast(300%) brightness(150%) hue-rotate(0deg);
}
25% {
transform: translate(5%, -5%) rotate(5deg);
filter: contrast(320%) brightness(160%) hue-rotate(15deg);
}
50% {
transform: translate(-5%, 5%) rotate(-5deg);
filter: contrast(340%) brightness(170%) hue-rotate(30deg);
}
75% {
transform: translate(3%, 3%) rotate(3deg);
filter: contrast(320%) brightness(160%) hue-rotate(15deg);
}
}
/* 深色模式增强效果 */
@media (prefers-color-scheme: dark) {
body::before {
background:
radial-gradient(ellipse at center, #00ff88 0%, transparent 80%),
radial-gradient(ellipse at 20% 80%, #ff0055 0%, transparent 60%);
filter: contrast(400%) brightness(200%);
mix-blend-mode: overlay;
animation:
fadeInBackgroundDark 1.2s ease-out 0.2s forwards,
rotateAndShift 6s ease-in-out 1.4s infinite;
}
body::after {
mix-blend-mode: soft-light;
animation: fadeInNoiseDark 1.2s ease-out 0.2s forwards;
}
@keyframes fadeInBackgroundDark {
to { opacity: 0.6; }
}
@keyframes fadeInNoiseDark {
to { opacity: 0.12; }
}
}
/* 移动端性能优化适配 */
@media (max-width: 768px) {
body::before {
filter: contrast(200%) brightness(120%);
animation:
fadeInBackgroundMobile 1.2s ease-out 0.2s forwards,
rotateAndShift 10s ease-in-out 1.4s infinite;
}
@keyframes fadeInBackgroundMobile {
to { opacity: 0.6; }
}
}
动态背景 Fragment Shader(片元着色器)版 2026年1月21日
✅️Html 代码 - 添加至 <body> 后
<!-- 动态背景绘制容器元素 -->
<canvas id="gl-canvas" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; opacity: 0.4; z-index: -1;"></canvas>
JavaScript 代码 - 添加至 </body> 前
<!-- 动态背景 JS 脚本 -->
<script>
// --- 颜色调色板 ---
const PALETTE = ['#86DFE9', '#A4EFF4', '#FDFFF0', '#D6F2C7'];
// --- 顶点着色器 ---
const VS_SOURCE = `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`;
// --- 片元着色器 ---
const FS_SOURCE = `
#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_resolution;
uniform vec3 u_color_0;
uniform vec3 u_color_1;
uniform vec3 u_color_2;
uniform vec3 u_color_3;
uniform float u_rand_1;
uniform float u_rand_2;
#define S(a,b,t) smoothstep(a,b,t)
mat2 Rot(float a) {
float s = sin(a);
float c = cos(a);
return mat2(c, -s, s, c);
}
// 噪点生成函数
vec2 hash( vec2 p ) {
p = vec2( dot(p,vec2(2127.1,81.17)), dot(p,vec2(1269.5,283.37)) );
return fract(sin(p)*43758.5453);
}
float noise( in vec2 p ) {
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( -1.0+2.0*hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( -1.0+2.0*hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( -1.0+2.0*hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( -1.0+2.0*hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 uv = gl_FragCoord.xy/u_resolution.xy;
vec2 tuv = uv;
// 缩放控制 - 数值越小纹理越大
tuv *= 1.3; // 原值 2.2
tuv -= .5;
// 动态扭曲与旋转
float degree = noise(vec2(u_time * 0.1, tuv.x*tuv.y));
tuv *= Rot( radians( ( degree - 0.5 ) * 540. + 180. ));
// 波浪扭曲
float frequency = 3.;
float amplitude = 100.;
float speed = 2.0;
tuv.x += sin( tuv.y * frequency + speed ) / amplitude;
tuv.y += sin( tuv.x * frequency * 1.2 + speed ) / ( amplitude * .5 );
// 颜色层混合
vec3 layer1 = mix( u_color_0, u_color_1, S( -0.6, .6, ( tuv * Rot( radians( u_rand_1 ))).x));
vec3 layer2 = mix( u_color_2, u_color_3, S( -0.6, .6, ( tuv * Rot( radians( u_rand_2 ))).x));
float verticalMix = S( 0.6, -0.1, tuv.y + noise(tuv * 0.5) * 0.3);
vec3 finalComp = mix(layer1, layer2, verticalMix);
// --- 胶片颗粒感 ---
float grain = fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453);
float grainStrength = 0.12; // 改变颗粒强弱 - 0.01细腻>0.2粗糙
finalComp += (grain - 0.5) * grainStrength;
gl_FragColor = vec4( finalComp, 1.0 );
}
`;
// --- WebGL 初始化 ---
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Shader compile error:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vsSource, fsSource) {
const vs = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
if (!vs || !fs) return null;
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Program link error:', gl.getProgramInfoLog(program));
return null;
}
return program;
}
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [
parseInt(result[1], 16) / 255,
parseInt(result[2], 16) / 255,
parseInt(result[3], 16) / 255
] : [0, 0, 0];
}
const canvas = document.getElementById('gl-canvas');
const gl = canvas.getContext('webgl', {
alpha: false
});
if (!gl) {
console.warn('WebGL not supported');
}
const program = createProgram(gl, VS_SOURCE, FS_SOURCE);
gl.useProgram(program);
// 定义覆盖全屏的矩形
const positions = new Float32Array([
-1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0,
]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// 获取变量地址
const uTimeLoc = gl.getUniformLocation(program, 'u_time');
const uResLoc = gl.getUniformLocation(program, 'u_resolution');
const uRand1Loc = gl.getUniformLocation(program, 'u_rand_1');
const uRand2Loc = gl.getUniformLocation(program, 'u_rand_2');
const colorLocs = [
gl.getUniformLocation(program, 'u_color_0'),
gl.getUniformLocation(program, 'u_color_1'),
gl.getUniformLocation(program, 'u_color_2'),
gl.getUniformLocation(program, 'u_color_3'),
];
// 传入颜色
function setColors(palette) {
palette.forEach((hex, index) => {
if (colorLocs[index]) {
gl.uniform3fv(colorLocs[index], hexToRgb(hex));
}
});
}
setColors(PALETTE);
// 传入随机旋转角度
let rand1 = Math.random() * 360;
let rand2 = Math.random() * 360;
gl.uniform1f(uRand1Loc, rand1);
gl.uniform1f(uRand2Loc, rand2);
// 窗口大小调整与性能优化 (限制 DPR)
function resize() {
const displayWidth = window.innerWidth;
const displayHeight = window.innerHeight;
// 限制最大像素比为 1.5 以优化性能
const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
canvas.width = displayWidth * dpr;
canvas.height = displayHeight * dpr;
gl.viewport(0, 0, canvas.width, canvas.height);
gl.uniform2f(uResLoc, canvas.width, canvas.height);
}
window.addEventListener('resize', resize);
resize();
let startTime = performance.now();
function render(time) {
const currentTime = (time - startTime) * 0.001;
gl.uniform1f(uTimeLoc, currentTime);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
</script>
✅️JavaScript 代码 - 优化强制的重排和淡入效果 - 添加至 </body> 前
<!-- 动态背景 JS 脚本 -->
<script>
(function() {
'use strict';
// --- 配置参数 ---
const CONFIG = {
PALETTE: ['#86DFE9', '#A4EFF4', '#FDFFF0', '#D6F2C7'],
INIT_DELAY: 100, // 延迟初始化时间,避免阻塞首屏
FADE_IN_DURATION: 1200 // 淡入动画时长
};
// --- 顶点着色器 ---
const VS_SOURCE = `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`;
// --- 片元着色器 ---
const FS_SOURCE = `
#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_resolution;
uniform vec3 u_color_0;
uniform vec3 u_color_1;
uniform vec3 u_color_2;
uniform vec3 u_color_3;
uniform float u_rand_1;
uniform float u_rand_2;
#define S(a,b,t) smoothstep(a,b,t)
mat2 Rot(float a) {
float s = sin(a);
float c = cos(a);
return mat2(c, -s, s, c);
}
// 噪点生成函数
vec2 hash( vec2 p ) {
p = vec2( dot(p,vec2(2127.1,81.17)), dot(p,vec2(1269.5,283.37)) );
return fract(sin(p)*43758.5453);
}
float noise( in vec2 p ) {
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( -1.0+2.0*hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( -1.0+2.0*hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( -1.0+2.0*hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( -1.0+2.0*hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 uv = gl_FragCoord.xy/u_resolution.xy;
vec2 tuv = uv;
// 缩放控制 - 数值越小纹理越模糊
tuv *= 1.3; // 原值 2.2
tuv -= .5;
float degree = noise(vec2(u_time * 0.1, tuv.x*tuv.y));
tuv *= Rot( radians( ( degree - 0.5 ) * 540. + 180. ));
float frequency = 3.;
float amplitude = 100.;
float speed = 2.0;
tuv.x += sin( tuv.y * frequency + speed ) / amplitude;
tuv.y += sin( tuv.x * frequency * 1.2 + speed ) / ( amplitude * .5 );
vec3 layer1 = mix( u_color_0, u_color_1, S( -0.6, .6, ( tuv * Rot( radians( u_rand_1 ))).x));
vec3 layer2 = mix( u_color_2, u_color_3, S( -0.6, .6, ( tuv * Rot( radians( u_rand_2 ))).x));
float verticalMix = S( 0.6, -0.1, tuv.y + noise(tuv * 0.5) * 0.3);
vec3 finalComp = mix(layer1, layer2, verticalMix);
// --- 胶片颗粒感 ---
float grain = fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453);
float grainStrength = 0.12; // 改变颗粒强弱 - 0.01细腻>0.2粗糙
finalComp += (grain - 0.5) * grainStrength;
gl_FragColor = vec4( finalComp, 1.0 ); // 片元始终不透明 透明度由 canvas CSS opacity 控制
}
`;
// --- WebGL 初始化 ---
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Shader compile error:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vsSource, fsSource) {
const vs = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
if (!vs || !fs) return null;
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Program link error:', gl.getProgramInfoLog(program));
return null;
}
return program;
}
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [
parseInt(result[1], 16) / 255,
parseInt(result[2], 16) / 255,
parseInt(result[3], 16) / 255
] : [0, 0, 0];
}
// --- 背景初始化逻辑 ---
function initBackground() {
const canvas = document.getElementById('gl-canvas');
if (!canvas) {
console.warn('Canvas element #gl-canvas not found.');
return;
}
// 读取 HTML 中设置的最终透明度
const targetOpacity = window.getComputedStyle(canvas).opacity;
// 将初始状态隐藏
canvas.style.opacity = '0';
try {
const gl = canvas.getContext('webgl', {
alpha: true, // 启用透明通道 支持 CSS 背景透视
antialias: false
});
if (!gl) {
console.warn('WebGL not supported');
canvas.style.opacity = targetOpacity;
return;
}
const program = createProgram(gl, VS_SOURCE, FS_SOURCE);
if (!program) {
console.error('Failed to create shader program');
canvas.style.opacity = targetOpacity;
return;
}
gl.useProgram(program);
// 定义覆盖全屏的矩形
const positions = new Float32Array([
-1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0,
]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// 获取变量地址
const uTimeLoc = gl.getUniformLocation(program, 'u_time');
const uResLoc = gl.getUniformLocation(program, 'u_resolution');
const uRand1Loc = gl.getUniformLocation(program, 'u_rand_1');
const uRand2Loc = gl.getUniformLocation(program, 'u_rand_2');
const colorLocs = [
gl.getUniformLocation(program, 'u_color_0'),
gl.getUniformLocation(program, 'u_color_1'),
gl.getUniformLocation(program, 'u_color_2'),
gl.getUniformLocation(program, 'u_color_3'),
];
// 传入颜色
function setColors(palette) {
palette.forEach((hex, index) => {
if (colorLocs[index]) {
gl.uniform3fv(colorLocs[index], hexToRgb(hex));
}
});
}
setColors(CONFIG.PALETTE);
// 传入随机旋转角度
let rand1 = Math.random() * 360;
let rand2 = Math.random() * 360;
gl.uniform1f(uRand1Loc, rand1);
gl.uniform1f(uRand2Loc, rand2);
// 窗口大小调整与性能优化 限制 DPR 1.5
let width, height;
function resize() {
const displayWidth = window.innerWidth;
const displayHeight = window.innerHeight;
const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
width = displayWidth * dpr;
height = displayHeight * dpr;
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
gl.uniform2f(uResLoc, width, height);
}
}
window.addEventListener('resize', resize);
resize();
let startTime = performance.now();
function render(time) {
const currentTime = (time - startTime) * 0.001;
gl.uniform1f(uTimeLoc, currentTime);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
// --- 触发淡入效果 ---
requestAnimationFrame(() => {
canvas.style.transition = `opacity ${CONFIG.FADE_IN_DURATION}ms ease-in-out`;
// 设置为 HTML 中定义的透明度 0.4
canvas.style.opacity = targetOpacity;
});
} catch (error) {
console.error('WebGL 初始化发生错误:', error);
canvas.style.opacity = targetOpacity; // 出错时也要恢复可见性
}
}
// --- 启动初始化流程 ---
function start() {
// 延迟初始化,避免阻塞关键渲染路径
setTimeout(() => {
initBackground();
}, CONFIG.INIT_DELAY);
}
// 在 DOM 加载完成后启动
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
})();
</script>
✅️将动态背景脚本添加至公用 script.js 文件中
第一步:添加配置和着色器代码,在文件顶部 “// assets/script.js” 注释下方添加。
// =============================
// 动态 WebGL 背景模块
// =============================
const WebGLBackground = (() => {
'use strict';
// --- 配置参数 ---
const CONFIG = {
PALETTE: ['#86DFE9', '#A4EFF4', '#FDFFF0', '#D6F2C7'],
INIT_DELAY: 100,
FADE_IN_DURATION: 1200
};
// --- 顶点着色器 ---
const VS_SOURCE = `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`;
// --- 片元着色器 ---
const FS_SOURCE = `
#ifdef GL_ES
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_resolution;
uniform vec3 u_color_0;
uniform vec3 u_color_1;
uniform vec3 u_color_2;
uniform vec3 u_color_3;
uniform float u_rand_1;
uniform float u_rand_2;
#define S(a,b,t) smoothstep(a,b,t)
mat2 Rot(float a) {
float s = sin(a);
float c = cos(a);
return mat2(c, -s, s, c);
}
vec2 hash( vec2 p ) {
p = vec2( dot(p,vec2(2127.1,81.17)), dot(p,vec2(1269.5,283.37)) );
return fract(sin(p)*43758.5453);
}
float noise( in vec2 p ) {
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( -1.0+2.0*hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( -1.0+2.0*hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( -1.0+2.0*hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( -1.0+2.0*hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 uv = gl_FragCoord.xy/u_resolution.xy;
vec2 tuv = uv;
tuv *= 1.3;
tuv -= .5;
float degree = noise(vec2(u_time * 0.1, tuv.x*tuv.y));
tuv *= Rot( radians( ( degree - 0.5 ) * 540. + 180. ));
float frequency = 3.;
float amplitude = 100.;
float speed = 2.0;
tuv.x += sin( tuv.y * frequency + speed ) / amplitude;
tuv.y += sin( tuv.x * frequency * 1.2 + speed ) / ( amplitude * .5 );
vec3 layer1 = mix( u_color_0, u_color_1, S( -0.6, .6, ( tuv * Rot( radians( u_rand_1 ))).x));
vec3 layer2 = mix( u_color_2, u_color_3, S( -0.6, .6, ( tuv * Rot( radians( u_rand_2 ))).x));
float verticalMix = S( 0.6, -0.1, tuv.y + noise(tuv * 0.5) * 0.3);
vec3 finalComp = mix(layer1, layer2, verticalMix);
float grain = fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453);
float grainStrength = 0.12;
finalComp += (grain - 0.5) * grainStrength;
gl_FragColor = vec4( finalComp, 1.0 );
}
`;
// --- WebGL 初始化工具函数 ---
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Shader compile error:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vsSource, fsSource) {
const vs = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
if (!vs || !fs) return null;
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Program link error:', gl.getProgramInfoLog(program));
return null;
}
return program;
}
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [
parseInt(result[1], 16) / 255,
parseInt(result[2], 16) / 255,
parseInt(result[3], 16) / 255
] : [0, 0, 0];
}
// --- 核心背景逻辑 ---
function initBackground() {
const canvas = document.getElementById('gl-canvas');
if (!canvas) {
console.warn('Canvas element #gl-canvas not found.');
return;
}
const targetOpacity = window.getComputedStyle(canvas).opacity;
canvas.style.opacity = '0';
try {
const gl = canvas.getContext('webgl', {
alpha: true,
antialias: false
});
if (!gl) {
console.warn('WebGL not supported');
canvas.style.opacity = targetOpacity;
return;
}
const program = createProgram(gl, VS_SOURCE, FS_SOURCE);
if (!program) {
console.error('Failed to create shader program');
canvas.style.opacity = targetOpacity;
return;
}
gl.useProgram(program);
const positions = new Float32Array([
-1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0,
]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
const uTimeLoc = gl.getUniformLocation(program, 'u_time');
const uResLoc = gl.getUniformLocation(program, 'u_resolution');
const uRand1Loc = gl.getUniformLocation(program, 'u_rand_1');
const uRand2Loc = gl.getUniformLocation(program, 'u_rand_2');
const colorLocs = [
gl.getUniformLocation(program, 'u_color_0'),
gl.getUniformLocation(program, 'u_color_1'),
gl.getUniformLocation(program, 'u_color_2'),
gl.getUniformLocation(program, 'u_color_3'),
];
function setColors(palette) {
palette.forEach((hex, index) => {
if (colorLocs[index]) {
gl.uniform3fv(colorLocs[index], hexToRgb(hex));
}
});
}
setColors(CONFIG.PALETTE);
let rand1 = Math.random() * 360;
let rand2 = Math.random() * 360;
gl.uniform1f(uRand1Loc, rand1);
gl.uniform1f(uRand2Loc, rand2);
let width, height;
function resize() {
const displayWidth = window.innerWidth;
const displayHeight = window.innerHeight;
const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
width = displayWidth * dpr;
height = displayHeight * dpr;
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
gl.uniform2f(uResLoc, width, height);
}
}
window.addEventListener('resize', resize);
resize();
let startTime = performance.now();
function render(time) {
const currentTime = (time - startTime) * 0.001;
gl.uniform1f(uTimeLoc, currentTime);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
requestAnimationFrame(() => {
canvas.style.transition = `opacity ${CONFIG.FADE_IN_DURATION}ms ease-in-out`;
canvas.style.opacity = targetOpacity;
});
} catch (error) {
console.error('WebGL 初始化发生错误:', error);
canvas.style.opacity = targetOpacity;
}
}
// 暴露启动方法
return {
start: () => {
setTimeout(() => {
initBackground();
}, CONFIG.INIT_DELAY);
}
};
})();
第二步:在 DOMContentLoaded 中调用,找到 script.js 文件中的document.addEventListener("DOMContentLoaded", function ()代码块,在函数内部initReplyForm();下一行添加 WebGLBackground.start();
WebGLBackground.start();