agent-Specialization/test/demo.html

325 lines
8.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>水面上涨动画特效</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
}
body {
background: #f5f5f5;
font-family: 'Arial', sans-serif;
display: flex;
justify-content: center;
align-items: center;
}
/* 示例内容 */
.content {
position: relative;
z-index: 1;
text-align: center;
color: #333;
text-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.content h1 {
font-size: 3em;
margin-bottom: 20px;
animation: fadeIn 1s ease-out;
}
.content p {
font-size: 1.2em;
animation: fadeIn 1.5s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 水面容器 */
.water-container {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 0%;
pointer-events: none;
overflow: visible;
}
/* 波浪层 */
.wave {
position: absolute;
bottom: 0;
left: 0;
width: 200%;
height: 100%;
background-repeat: repeat-x;
background-position: bottom;
}
.wave1 { z-index: 1; }
.wave2 { z-index: 2; }
.wave3 { z-index: 3; }
/* 触发按钮 */
.trigger-btn {
position: fixed;
top: 20px;
right: 20px;
padding: 12px 24px;
background: rgba(33, 150, 243, 0.8);
border: 2px solid #2196F3;
color: white;
font-size: 16px;
cursor: pointer;
border-radius: 25px;
z-index: 1000;
transition: all 0.3s;
backdrop-filter: blur(10px);
}
.trigger-btn:hover {
background: rgba(33, 150, 243, 1);
transform: scale(1.05);
}
</style>
</head>
<body>
<!-- 页面原本的内容 -->
<div class="content">
<h1>🌊 彩蛋特效</h1>
<p>水面正在缓缓上涨...</p>
<p style="margin-top: 10px; font-size: 0.9em; opacity: 0.8;">
每次刷新都有不同的波浪效果
</p>
</div>
<!-- 水面动画容器 -->
<div class="water-container" id="waterContainer">
<div class="wave wave1"></div>
<div class="wave wave2"></div>
<div class="wave wave3"></div>
</div>
<!-- 重新触发按钮 -->
<button class="trigger-btn" onclick="restartAnimation()">🔄 重播动画</button>
<script>
// 随机数工具函数
function random(min, max) {
return Math.random() * (max - min) + min;
}
function randomInt(min, max) {
return Math.floor(random(min, max));
}
function randomChoice(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
// 生成随机波浪SVG路径 - 相邻波振幅变化平滑
function generateWaveSVG(waveIndex) {
const baseHeight = 180 + waveIndex * 10; // 基准高度
const numWaves = 4; // 生成4个完整波段
let path = `M0,${baseHeight}`;
let currentX = 0;
// 第一个波的振幅随机
let prevAmplitude = random(40, 80);
// 生成多个完整的波段,每个包含波峰和波谷
for (let i = 0; i < numWaves; i++) {
// 每个波段的随机参数
const waveLength = random(700, 900); // 整个周期的长度700-900
// 振幅限制与前一个波的差值不超过20
let amplitude;
if (i === 0) {
amplitude = prevAmplitude;
} else {
const minAmp = Math.max(10, prevAmplitude - 20);
const maxAmp = Math.min(80, prevAmplitude + 20);
amplitude = random(minAmp, maxAmp);
}
prevAmplitude = amplitude;
const halfWave = waveLength / 2;
// 前半段:基线 → 波峰 → 基线
const peak1X = currentX + halfWave / 2;
const peak1Y = baseHeight - amplitude;
const mid1X = currentX + halfWave;
const mid1Y = baseHeight;
path += ` Q${peak1X},${peak1Y} ${mid1X},${mid1Y}`;
// 后半段:基线 → 波谷 → 基线
const trough1X = mid1X + halfWave / 2;
const trough1Y = baseHeight + amplitude;
const end1X = currentX + waveLength;
const end1Y = baseHeight;
path += ` Q${trough1X},${trough1Y} ${end1X},${end1Y}`;
currentX = end1X;
}
// 闭合路径
path += ` L${currentX},1000 L0,1000 Z`;
return {
path: path,
width: currentX,
waveWidth: currentX / numWaves // 平均波长
};
}
// 初始化水面动画
function initWaterAnimation() {
const container = document.getElementById('waterContainer');
const waves = document.querySelectorAll('.wave');
// 波浪颜色配置
const waveColors = [
'rgba(135, 206, 250, 0.4)',
'rgba(100, 181, 246, 0.5)',
'rgba(33, 150, 243, 0.4)'
];
// 创建动态样式表
const styleSheet = document.createElement('style');
styleSheet.id = 'dynamic-waves-style';
document.head.appendChild(styleSheet);
// 1. 随机水面上涨参数
const riseDuration = random(30, 40); // 8-12秒
const finalHeight = random(87, 93); // 87-93%
const riseEasing = randomChoice([
'ease-in-out',
'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
'cubic-bezier(0.42, 0, 0.58, 1)'
]);
// 创建水面上涨动画
const riseKeyframes = `
@keyframes waterRise {
0% { height: 0%; }
100% { height: ${finalHeight}%; }
}
`;
styleSheet.sheet.insertRule(riseKeyframes, 0);
container.style.animation = `waterRise ${riseDuration}s ${riseEasing} forwards`;
// 随机生成方向组合:两左一右 或 两右一左
const directions = randomChoice([
[1, 1, -1], // 两右一左
[1, -1, -1], // 一右两左
[-1, 1, 1], // 一左两右
[-1, -1, 1] // 两左一右
]);
// 2. 为每个波浪生成随机参数
waves.forEach((wave, index) => {
// 生成随机波浪形状
const svgData = generateWaveSVG(index);
const color = waveColors[index];
// 创建SVG
const svg = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${svgData.width} 1000' preserveAspectRatio='none'><path d='${svgData.path}' fill='${color}'/></svg>`;
const dataUrl = `data:image/svg+xml,${encodeURIComponent(svg)}`;
// 应用背景
wave.style.backgroundImage = `url("${dataUrl}")`;
wave.style.backgroundSize = `${svgData.waveWidth}px 100%`;
// 为每层设置不同的速度范围,确保速度差异明显
let duration;
if (index === 0) {
duration = random(16, 22); // 第一层:慢速
} else if (index === 1) {
duration = random(11, 16); // 第二层:中速
} else {
duration = random(7, 12); // 第三层:快速
}
const direction = directions[index]; // 使用预设的方向
const distance = svgData.waveWidth * direction;
const initialPos = randomInt(-200, 200); // 随机初始位置
const delay = random(0, 1.5); // 随机延迟 0-1.5秒
// 创建波浪移动动画
const moveKeyframes = `
@keyframes wave${index + 1}Move {
0% { background-position-x: ${initialPos}px; }
100% { background-position-x: ${initialPos + distance}px; }
}
`;
styleSheet.sheet.insertRule(moveKeyframes, 0);
// 应用动画
wave.style.animation = `wave${index + 1}Move ${duration}s linear infinite`;
wave.style.animationDelay = `${delay}s`;
wave.style.backgroundPositionX = `${initialPos}px`;
});
console.log(`🌊 水面动画已生成
- 上涨时长: ${riseDuration.toFixed(1)}
- 最终高度: ${finalHeight.toFixed(1)}%
- 缓动效果: ${riseEasing}
- 波浪方向: [${directions.map(d => d > 0 ? '→' : '←').join(', ')}]`);
}
// 重新播放动画
function restartAnimation() {
// 移除旧的动态样式
const oldStyle = document.getElementById('dynamic-waves-style');
if (oldStyle) {
oldStyle.remove();
}
// 重置容器
const container = document.getElementById('waterContainer');
container.style.animation = 'none';
container.style.height = '0%';
// 重置所有波浪
const waves = document.querySelectorAll('.wave');
waves.forEach(wave => {
wave.style.animation = 'none';
wave.style.animationDelay = '0s';
wave.style.backgroundPositionX = '0px';
});
// 强制重绘
void container.offsetHeight;
// 重新初始化
setTimeout(() => {
initWaterAnimation();
}, 50);
}
// 页面加载时初始化
window.addEventListener('load', initWaterAnimation);
</script>
</body>
</html>