2025-05-27 15:46:31 +08:00

145 lines
4.9 KiB
HTML
Executable File

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enhanced AI Voice Assistant Ball</title>
<style>
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #00003300;
overflow: hidden;
}
.ai-ball {
width: 40px;
height: 40px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #ff00ff, #00ffff);
position: relative;
overflow: hidden;
box-shadow: 0 0 30px rgba(255, 255, 255, 0.3);
animation: breathe 4s infinite ease-in-out;
transition: transform 0.5s ease, animation-duration 0.5s ease, background 0.5s ease;
}
@keyframes breathe {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.wave {
position: absolute;
width: 400%;
height: 400%;
top: -150%;
left: -150%;
background: radial-gradient(ellipse at center, transparent 30%, rgba(255, 255, 255, 0.2) 70%);
animation: wave 16s infinite linear;
}
@keyframes wave {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.glow {
position: absolute;
width: 100%;
height: 100%;
background: radial-gradient(circle at center, rgba(255, 255, 255, 0.8) 0%, transparent 70%);
opacity: 0;
animation: pulse 2s infinite alternate;
transition: opacity 0.5s ease;
}
@keyframes pulse {
0% { opacity: 0.2; transform: scale(0.8); }
100% { opacity: 0.6; transform: scale(1.2); }
}
.color-shift {
position: absolute;
width: 100%;
height: 100%;
background: radial-gradient(circle at 30% 30%, #ff00ff, #00ffff);
mix-blend-mode: color;
animation: colorShift 8s infinite alternate;
}
@keyframes colorShift {
0% { filter: hue-rotate(0deg); }
100% { filter: hue-rotate(15deg); }
}
</style>
</head>
<body>
<div class="ai-ball">
<div class="wave"></div>
<div class="glow"></div>
<div class="color-shift"></div>
</div>
<script>
const aiBall = document.querySelector('.ai-ball');
let audioContext = new (window.AudioContext || window.webkitAudioContext)();
let analyser = audioContext.createAnalyser();
let microphone;
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
microphone = audioContext.createMediaStreamSource(stream);
microphone.connect(analyser);
analyser.fftSize = 256;
loop();
})
.catch(err => console.error("Access to microphone denied:", err));
function loop() {
window.requestAnimationFrame(loop);
let dataArray = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(dataArray);
let sum = dataArray.reduce((a, b) => a + b, 0);
let average = sum / dataArray.length;
let volume = average / 128.0;
adjustAnimation(volume);
adjustColor(volume);
}
// function loop() {
// const now = Date.now();
// if (now - lastUpdateTime > updateInterval) {
// lastUpdateTime = now;
// let dataArray = new Uint8Array(analyser.frequencyBinCount);
// analyser.getByteFrequencyData(dataArray);
// let sum = dataArray.reduce((a, b) => a + b, 0);
// let average = sum / dataArray.length;
// let volume = average / 128.0;
// adjustAnimation(volume);
// adjustColor(volume);
// }
// window.requestAnimationFrame(loop);
// }
function adjustAnimation(volume) {
let scale = 1 + volume * 0.5; // Increase scale range
let speed = 2 - Math.min(0.5, volume * 0.5); // Increase speed sensitivity
let opacity = 0.2 + volume * 0.5; // Adjust glow opacity based on volume
aiBall.style.transform = `scale(${scale})`;
aiBall.style.animationDuration = `${speed}s`;
let glow = aiBall.querySelector('.glow');
if (glow) {
glow.style.opacity = opacity;
}
}
function adjustColor(volume) {
let hueRotation = volume * -15; // Full hue rotation based on max volume
aiBall.style.filter = `hue-rotate(${hueRotation}deg)`;
}
</script>
</body>
</html>