只为你绽放
<meta charset="utf-8"><style>
#papa{margin:130px 0 20px calc(50% - 781px);width:1400px;height:850px;background:lightblue url('https://cccimg.com/view.php/2c2334bf5d7804d9ca358b78bbe921e0.gif') no-repeat center/cover;box-shadow:3px 3px 6px gray;z-index:1;overflow:hidden;user-select:none;display:grid;place-items:center;position:relative;--state:running;border-radius:32px;}
zxx-slide{display:block;width:100%;height:100%;position:absolute;}
.zxx-slide-a{width:100%;height:110%;position:absolute;bottom:-50px;display:none;}
.zxx-slide-a.in{z-index:1;}
.zxx-slide-img{width:100%;height:100%;object-fit:cover;pointer-events:none;display:block;}
.zxx-slide-index-x{position:absolute;left:0px;right:0;bottom:0px;text-align:center;font-size:0;z-index:1;}
@keyframes seed{0%{--seed:0}1%{--seed:1}2%{--seed:2}3%{--seed:3}4%{--seed:4}5%{--seed:5}6%{--seed:6}7%{--seed:7}8%{--seed:8}9%{--seed:9}10%{--seed:10}11%{--seed:11}12%{--seed:12}13%{--seed:13}14%{--seed:14}15%{--seed:15}16%{--seed:16}17%{--seed:17}18%{--seed:18}19%{--seed:19}20%{--seed:20}21%{--seed:21}22%{--seed:22}23%{--seed:23}24%{--seed:24}25%{--seed:25}26%{--seed:26}27%{--seed:27}28%{--seed:28}29%{--seed:29}30%{--seed:30}31%{--seed:31}32%{--seed:32}33%{--seed:33}34%{--seed:34}35%{--seed:35}36%{--seed:36}37%{--seed:37}38%{--seed:38}39%{--seed:39}40%{--seed:40}41%{--seed:41}42%{--seed:42}43%{--seed:43}44%{--seed:44}45%{--seed:45}46%{--seed:46}47%{--seed:47}48%{--seed:48}49%{--seed:49}50%{--seed:50}51%{--seed:51}52%{--seed:52}53%{--seed:53}54%{--seed:54}55%{--seed:55}56%{--seed:56}57%{--seed:57}58%{--seed:58}59%{--seed:59}60%{--seed:60}61%{--seed:61}62%{--seed:62}63%{--seed:63}64%{--seed:64}65%{--seed:65}66%{--seed:66}67%{--seed:67}68%{--seed:68}69%{--seed:69}70%{--seed:70}71%{--seed:71}72%{--seed:72}73%{--seed:73}74%{--seed:74}75%{--seed:75}76%{--seed:76}77%{--seed:77}78%{--seed:78}79%{--seed:79}80%{--seed:80}81%{--seed:81}82%{--seed:82}83%{--seed:83}84%{--seed:84}85%{--seed:85}86%{--seed:86}87%{--seed:87}88%{--seed:88}89%{--seed:89}90%{--seed:90}91%{--seed:91}92%{--seed:92}93%{--seed:93}94%{--seed:94}95%{--seed:95}96%{--seed:96}97%{--seed:97}98%{--seed:98}99%{--seed:99}100%{--seed:100}}
.zxx-slide-a.effect-round{-webkit-mask:radial-gradient(#000 calc(1% * var(--seed)), transparent calc(1% * var(--seed)));-webkit-mask-size:50px 50px;mask:radial-gradient(#000 calc(1% * var(--seed)), transparent calc(1% * var(--seed)));mask-size:50px 50px;animation:seed 1s ease-out;}
.zxx-slide-a.effect-topdown{-webkit-mask:linear-gradient(to bottom, #000 calc(1% * var(--seed)), transparent calc(1% * var(--seed)));mask:linear-gradient(to bottom, #000 calc(1% * var(--seed)), transparent calc(1% * var(--seed)));-webkit-mask-size:100% 100%;mask-size:100% 100%;animation:seed 1s ease-out;}
@keyframes fadeIn{0%{opacity:0;}100%{opacity:1;}}
.zxx-slide-a.effect-fade{mask:none;-webkit-mask:none;animation:fadeIn 1s ease-out forwards;}
@keyframes blurToClear{from{filter:blur(20px);opacity:0;}to{filter:blur(0);opacity:1;}}
.zxx-slide-a.effect-clear{mask:none;-webkit-mask:none;animation:blurToClear 1.5s ease-out forwards;}
.block-effect-wrapper{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:grid;pointer-events:none;}
.dissolve-wrapper{grid-template-columns:repeat(30, 1fr);grid-template-rows:repeat(20, 1fr);}
.pixelate-wrapper{grid-template-columns:repeat(40, 1fr);grid-template-rows:repeat(30, 1fr);}
.mosaic-wrapper{grid-template-columns:repeat(15, 1fr);grid-template-rows:repeat(10, 1fr);}
.block-piece{background-color:#006400;transition:all 1.2s;opacity:0.6;border-radius:2%;transform:scale(1);box-shadow:0px 0px 0px 2px #ffffff;}
.shatter-wrapper{perspective:1500px;position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;pointer-events:none;}
.shatter-piece{position:absolute;background:no-repeat center/cover;transition:transform 1.4s, opacity 1s;transform-origin:center;opacity:1;}
@keyframes blockHide{to{transform:scale(0);opacity:0;}}
.zxx-slide-a.effect-dissolve .block-piece,.zxx-slide-a.effect-pixelate .block-piece,.zxx-slide-a.effect-mosaic .block-piece{animation:blockHide 1.2s ease-out forwards;}
.zxx-slide-a.effect-shatter .shatter-piece{transform:translate3d(100px, -100px, -500px) rotate(180deg);opacity:0;}
.lyrics{margin:0;z-index:20;top:92%;left:50%;transform:translate(-50%, -50%);height:100px;text-align:center;position:absolute;}
.lyric-line{width:100%;position:relative;height:60px;overflow:visible;font:300 50px '华文行楷', sans-serif;line-height:60px;text-align:left;white-space:nowrap;filter:drop-shadow(#fff 1px 0 0) drop-shadow(#fff 0 1px 0) drop-shadow(#fff -1px 0 0) drop-shadow(#fff 0 -1px 0);}
.lyric-mask{position:absolute;color:transparent;background:linear-gradient(90deg,cyan,teal);background-clip:text;-webkit-background-clip:text;text-shadow:1px 1px 1px rgba(0,0,0,.45);white-space:nowrap;}
.lyric-original{color:#ADFF2F;white-space:nowrap;}
#fullscreen{position:absolute;top:30px;left:30px;font:normal 1.5em 楷体;color:#fff;text-shadow:0 0 3px #000;opacity:1;cursor:pointer;user-select:none;z-index:8;}
#fullscreen:hover{font-style:italic;}
.spectrum-player{position:absolute;top:4%;right:2%;z-index:30;width:110px;height:110px;cursor:pointer;user-select:none;filter:none;box-shadow:none;}
.progress-ring-svg{position:absolute;top:0;left:0;width:100%;height:100%;transform:rotate(-90deg);filter:none;}
.progress-ring-circle{fill:none;stroke:#ffd700;stroke-width:2.5;stroke-linecap:round;stroke-dasharray:238.76;stroke-dashoffset:238.76;transition:stroke-dashoffset 0.08s linear;}
#fireworksCanvas{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:31;}
.spectrum-dots{position:absolute;width:100%;height:100%;top:0;left:0;pointer-events:none;transform:translate(-3px, -3px);}
.spectrum-dot{position:absolute;width:6px;height:6px;border-radius:50%;background:#ffaa33;box-shadow:0 0 4px #ffcc55, 0 0 2px #ffaa44;transform-origin:center;transition:transform 0.05s linear, background 0.05s linear, box-shadow 0.05s ease;will-change:transform, background, box-shadow;}
.center-btn{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);width:70px;height:70px;border-radius:50%;background:rgba(0, 0, 0, 0.45);backdrop-filter:blur(8px);border:1px solid rgba(255, 215, 0, 0.9);display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer;transition:all 0.2s;z-index:5;font-family:'Microsoft YaHei', monospace;text-align:center;color:#ffd700;text-shadow:0 0 2px #ff0000;line-height:1.2;box-shadow:none;}
.center-btn:hover{background:rgba(0, 0, 0, 0.8);border-color:#ffaa00;transform:translate(-50%, -50%) scale(1.02);box-shadow:none;}
.time-remain{font-size:18px;font-family:monospace;margin-top:2px;}
@media (max-width:1000px){.spectrum-player{width:95px;height:95px;}.center-btn{width:60px;height:60px;}.time-remain{font-size:10px;}}
</style>
<div id="papa">
<div class="spectrum-player" id="spectrumPlayer">
<canvas id="fireworksCanvas"></canvas>
<svg class="progress-ring-svg" viewBox="0 0 110 110">
<circle class="progress-ring-circle" cx="55" cy="55" r="38"></circle>
</svg>
<div class="spectrum-dots" id="spectrumDots"></div>
<div class="center-btn" id="centerBtn">
<div class="time-remain" id="btnTimeRemain">-00:00</div>
</div>
</div>
<zxx-slide>
<div class="zxx-slide-x">
<p class="zxx-slide-a">
<video class="zxx-slide-img" src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/701485d0b5bfae8158342acdccd271c1_preview.mp4" loop muted autoplay preload="auto" playsinline></video>
<p class="zxx-slide-a">
<video class="zxx-slide-img" src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/53b4e149ea039f14fded82e4e9a04f27_preview.mp4" loop muted autoplay preload="auto" playsinline></video></p>
<p class="zxx-slide-a">
<video class="zxx-slide-img" src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/d6df4b8d6c0474b2290825fdce256825_preview.mp4" loop muted autoplay preload="auto" playsinline></video></p>
</div>
</zxx-slide>
<span id="fullscreen">全屏欣赏</span>
<div class="lyrics">
<div class="lyric-line">
<div class="lyric-mask"></div>
<div class="lyric-original"></div>
</div>
</div>
</div>
<audio id="audio" src="https://www.joy127.com/url/151698.mp3" autoplay loop></audio>
<script>
var eleZxxSlides = document.querySelectorAll('zxx-slide');
const effectList = ['effect-round','effect-topdown','effect-fade','effect-clear','effect-dissolve','effect-pixelate','effect-mosaic','effect-shatter'];
[].slice.call(eleZxxSlides).forEach(function (container) {
var timerSlide = null;
var indexSlide = 0;
var ANIMATION_DURATION = 1200;
var WAIT_DURATION = 8800;
var TOTAL_INTERVAL = ANIMATION_DURATION + WAIT_DURATION;
var eleSlides = [].slice.call(container.querySelectorAll('p'));
function getRandomEffect(){
let ran = Math.floor(Math.random() * effectList.length);
return effectList;
}
function createEffectLayer(slide, effect) {
let oldLayer = slide.querySelector('.block-effect-wrapper, .shatter-wrapper');
if(oldLayer) oldLayer.remove();
let imgSrc = slide.querySelector('.zxx-slide-img')?.poster || '';
let video = slide.querySelector('.zxx-slide-img');
if(video && video.poster) imgSrc = video.poster;
if(effect === 'effect-dissolve' || effect === 'effect-pixelate' || effect === 'effect-mosaic'){
let wrapper = document.createElement('div');
wrapper.className = `block-effect-wrapper ${effect.replace('effect-','')}-wrapper`;
let cols = wrapper.classList.contains('dissolve-wrapper') ? 30 : wrapper.classList.contains('pixelate-wrapper') ? 40 : 15;
let rows = wrapper.classList.contains('dissolve-wrapper') ? 20 : wrapper.classList.contains('pixelate-wrapper') ? 30 : 10;
let total = cols * rows;
for(let i=0; i<total; i++){
let piece = document.createElement('div');
piece.className = 'block-piece';
wrapper.appendChild(piece);
}
slide.appendChild(wrapper);
}
else if(effect === 'effect-shatter'){
let wrapper = document.createElement('div');
wrapper.className = 'shatter-wrapper';
let cols = 8, rows = 5;
let w = 100/cols, h = 100/rows;
for(let y=0; y<rows; y++){
for(let x=0; x<cols; x++){
let piece = document.createElement('div');
piece.className = 'shatter-piece';
piece.style.width = w+'%';
piece.style.height = h+'%';
piece.style.left = x*w+'%';
piece.style.top = y*h+'%';
piece.style.backgroundImage = `url(${imgSrc})`;
piece.style.backgroundPosition = `${-x*w}% ${-y*h}%`;
wrapper.appendChild(piece);
}
}
slide.appendChild(wrapper);
}
}
function showCurrentSlide(){
eleSlides.forEach(function (slide, index) {
if (indexSlide == index) {
effectList.forEach(eff=>slide.classList.remove(eff));
let randEff = getRandomEffect();
createEffectLayer(slide, randEff);
slide.classList.add('in', randEff);
slide.style.display = 'block';
} else {
slide.classList.remove('in');
effectList.forEach(eff=>slide.classList.remove(eff));
slide.style.display = 'none';
}
});
}
function nextSlide(){
indexSlide++;
if (indexSlide >= eleSlides.length) indexSlide = 0;
showCurrentSlide();
if(!audio.paused){
timerSlide = setTimeout(nextSlide, TOTAL_INTERVAL);
}
}
showCurrentSlide();
function startLoop(){
clearTimeout(timerSlide);
timerSlide = setTimeout(nextSlide, TOTAL_INTERVAL);
}
function stopLoop(){
clearTimeout(timerSlide);
}
audio.addEventListener('play', startLoop);
audio.addEventListener('pause', stopLoop);
if(!audio.paused){
startLoop();
}
});
</script>
<script>
const lrc = `只为你绽放
Hmmm
Mmmm
Mmmm
LRC编辑:醉美水芙蓉
Comparing you to a flower that blooms
Blooms only once
When I have only that your beauty stands
Will you forget each other?
After a long time
Will there be someone else crossing our line
I hope you are still here
Just want to know how are you?
And how is your life today?
I traveled to meet you
I just want to see
Your face that's all I need
It's okay
I understand the miles we've grown
I just want to keep the story
Keep the smile we've known
Deep down in case in the end we don't meet
I want you to know that I just want that so sweet
I hope you are still here
Just want to know how are you?
And how is your life today?
I traveled to meet you
I just want to see
Your face that's all I need
Sometimes we open our eyes wake up and forget
Hmmm
Something's missing deep inside a feeling unmet
Hmmm
But in the quiet of the night your memory stays
Guiding me through the shadows lighting up my days
I hope you are still here
Just want to know how are you?
And how is your life today?
I traveled to meet you
I just want to see
Your face that's all I need
谢谢欣赏!
`;
const audio = document.getElementById('audio');
const lyrics = parseLyrics(lrc);
const lyricMask = document.querySelector('.lyric-mask');
const lyricOriginal = document.querySelector('.lyric-original');
let currentIndex = -1;
let currentLyric = null;
function parseLyrics(lrcText) {
const lyrics = [];
const lines = lrcText.split('\n').filter(line => line.trim());
lines.forEach((line, index) => {
const timeMatch = line.match(/\[(\d+:\d+\.\d+)\]/);
if (timeMatch) {
const timeStr = timeMatch;
const text = line.replace(/\[.*?\]/g, '').trim();
if (text) {
const startTime = timeToMs(timeStr);
const nextLine = lines;
const nextTimeMatch = nextLine ? nextLine.match(/\[(\d+:\d+\.\d+)\]/) : null;
const endTime = nextTimeMatch ? timeToMs(nextTimeMatch) : startTime + 5000;
lyrics.push({
startTime,
endTime,
text,
durations: calculateCharDurations(text, startTime, endTime)
});
}
}
});
return lyrics;
}
function calculateCharDurations(text, startTime, endTime) {
const totalDuration = endTime - startTime;
const charCount = text.length;
const baseDur = Math.floor(totalDuration / charCount);
const durations = new Array(charCount).fill(baseDur);
const remainder = totalDuration % charCount;
for (let i = 0; i < remainder; i++) {
durations++;
}
return durations;
}
function timeToMs(timeStr) {
const parts = timeStr.split(':');
const minutes = parseInt(parts, 10);
const secondsAndMs = parts.split('.');
const seconds = parseInt(secondsAndMs, 10);
const ms = parseInt(secondsAndMs || 0, 10);
return minutes * 60 * 1000 + seconds * 1000 + ms;
}
function getCurrentLyricIndex(lyrics, currentTimeMs) {
for (let i = 0; i < lyrics.length; i++) {
if (currentTimeMs >= lyrics.startTime && currentTimeMs <= lyrics.endTime) {
return i;
}
}
return -1;
}
function updateLyricDisplay(index) {
if (index < 0 || index >= lyrics.length) return;
currentIndex = index;
currentLyric = lyrics;
lyricOriginal.textContent = currentLyric.text;
lyricMask.textContent = currentLyric.text;
lyricMask.style.width = '0';
}
function updateLyricMask(currentTimeMs) {
if (!currentLyric) return;
const elapsed = currentTimeMs - currentLyric.startTime;
const totalDuration = currentLyric.durations.reduce((a, b) => a + b, 0);
let charIndex = 0;
let accumulated = 0;
for (let i = 0; i < currentLyric.durations.length; i++) {
accumulated += currentLyric.durations;
if (elapsed <= accumulated) {
charIndex = i + 1;
break;
}
}
if (elapsed >= totalDuration) charIndex = currentLyric.text.length;
charIndex = Math.min(charIndex, currentLyric.text.length);
const temp = document.createElement('span');
temp.style.cssText = 'visibility:hidden;position:absolute;font:300 50px "华文隶书"';
document.body.appendChild(temp);
temp.textContent = currentLyric.text.substring(0, charIndex);
lyricMask.style.width = temp.offsetWidth + 'px';
document.body.removeChild(temp);
}
audio.addEventListener('timeupdate', () => {
const now = audio.currentTime * 1000;
const idx = getCurrentLyricIndex(lyrics, now);
if (idx !== currentIndex) updateLyricDisplay(idx);
updateLyricMask(now);
});
updateLyricDisplay(0);
let state = { isPlaying: false, isDragging: false };
const dom = {
spectrumPlayer: document.getElementById('spectrumPlayer'),
progressCircle: document.querySelector('.progress-ring-circle'),
centerBtn: document.getElementById('centerBtn'),
btnTimeRemain: document.getElementById('btnTimeRemain'),
fireworksCanvas: document.getElementById('fireworksCanvas'),
audio: document.getElementById('audio')
};
const innerRadius = 38;
const circumference = 2 * Math.PI * innerRadius;
let spectrumAnimationId = null, spectrumDots = [];
const totalDots = 24;
let globalRotationRad = 0;
const ROTATION_SPEED = 0.0068;
let originalAngles = [];
let dotRadius = 0;
let dotCenter = { x: 0, y: 0 };
const fwCtx = dom.fireworksCanvas.getContext('2d');
let particles = [];
let fwWidth, fwHeight, fwCenterX, fwCenterY;
function resizeFireworksCanvas() {
fwWidth = dom.spectrumPlayer.clientWidth;
fwHeight = dom.spectrumPlayer.clientHeight;
dom.fireworksCanvas.width = fwWidth;
dom.fireworksCanvas.height = fwHeight;
fwCenterX = fwWidth / 2;
fwCenterY = fwHeight / 2;
}
resizeFireworksCanvas();
window.addEventListener('resize', resizeFireworksCanvas);
class Particle {
constructor(angle, speed, color) {
this.x = fwCenterX;
this.y = fwCenterY;
this.vx = Math.cos(angle) * speed;
this.vy = Math.sin(angle) * speed;
this.alpha = 1;
this.life = 1;
this.radius = Math.random() * 2 + 1;
this.color = color;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.life -= 0.02;
this.alpha = this.life;
}
draw(ctx) {
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
}
}
function emitFireworks(intensity) {
const count = Math.floor(intensity * 8);
const baseSpeed = 1.5 + intensity * 2;
const colors = ['#ffdd00', '#ff8800', '#ff4444', '#ffffff'];
for (let i = 0; i < count; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = baseSpeed * (0.5 + Math.random() * 0.5);
const color = colors;
particles.push(new Particle(angle, speed, color));
}
}
function animateFireworks() {
fwCtx.clearRect(0, 0, fwWidth, fwHeight);
particles = particles.filter(p => p.life > 0);
particles.forEach(p => {
p.update();
p.draw(fwCtx);
});
if (state.isPlaying) {
requestAnimationFrame(animateFireworks);
} else {
fwCtx.clearRect(0, 0, fwWidth, fwHeight);
}
}
function updateDotGeometry() {
const w = dom.spectrumPlayer.clientWidth;
const h = dom.spectrumPlayer.clientHeight;
dotCenter.x = w / 2;
dotCenter.y = h / 2;
dotRadius = Math.min(w, h) * 0.52;
}
function rebuildSpectrumDots() {
const container = document.getElementById('spectrumDots');
if (!container) return;
container.innerHTML = '';
spectrumDots = [];
originalAngles = [];
updateDotGeometry();
for (let i = 0; i < totalDots; i++) {
const angle = (i / totalDots) * 2 * Math.PI;
originalAngles.push(angle);
const dot = document.createElement('div');
dot.className = 'spectrum-dot';
const x = dotCenter.x + dotRadius * Math.cos(angle);
const y = dotCenter.y + dotRadius * Math.sin(angle);
dot.style.left = `${x}px`;
dot.style.top = `${y}px`;
container.appendChild(dot);
spectrumDots.push(dot);
}
}
function updateDotsPosition() {
for (let i = 0; i < spectrumDots.length; i++) {
const dot = spectrumDots;
const rawAngle = originalAngles;
const finalAngle = rawAngle + globalRotationRad;
const px = dotCenter.x + dotRadius * Math.cos(finalAngle);
const py = dotCenter.y + dotRadius * Math.sin(finalAngle);
dot.style.left = `${px}px`;
dot.style.top = `${py}px`;
}
}
let resizeTimeout;
function handleResize() {
if (resizeTimeout) clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
if (!dom.spectrumPlayer) return;
const wasPlaying = state.isPlaying;
if (wasPlaying && spectrumAnimationId) {
cancelAnimationFrame(spectrumAnimationId);
spectrumAnimationId = null;
}
updateDotGeometry();
rebuildSpectrumDots();
updateDotsPosition();
if (wasPlaying) startSpectrumAnimation();
}, 100);
}
window.addEventListener('resize', handleResize);
function formatNegativeTime(seconds) {
if (isNaN(seconds) || !isFinite(seconds) || seconds <= 0) return "-00:00";
const mins = Math.floor(seconds / 60), secs = Math.floor(seconds % 60);
return `-${mins}:${secs < 10 ? '0' : ''}${secs}`;
}
function updateProgressCircle() {
if (!dom.audio.duration) return;
const progress = dom.audio.currentTime / dom.audio.duration;
dom.progressCircle.style.strokeDashoffset = circumference * (1 - progress);
dom.btnTimeRemain.textContent = formatNegativeTime(dom.audio.duration - dom.audio.currentTime);
dom.progressCircle.style.stroke = `hsl(${40 + progress * 20}, 100%, 55%)`;
}
function generateSpectrum() {
const t = Date.now() / 250;
let maxVal = 0;
const data = [];
for (let i = 0; i < totalDots; i++) {
let val = 0.4 + Math.sin(t + i * 0.3) * 0.4 + Math.random() * 0.3;
val = Math.min(1.0, Math.max(0.3, val));
data.push(val);
if(val > maxVal) maxVal = val;
}
return {data, intensity: maxVal};
}
function startSpectrumAnimation() {
if (spectrumAnimationId) cancelAnimationFrame(spectrumAnimationId);
if (!state.isPlaying) return;
animateFireworks();
function animate() {
if (!state.isPlaying) return;
globalRotationRad += ROTATION_SPEED;
if (globalRotationRad > Math.PI * 2) globalRotationRad -= Math.PI * 2;
updateDotsPosition();
const {data, intensity} = generateSpectrum();
if (intensity > 0.68) emitFireworks(intensity);
for (let i = 0; i < spectrumDots.length; i++) {
const dot = spectrumDots;
const val = data;
const scale = 0.7 + val * 0.9;
dot.style.transform = `scale(${scale})`;
const hue = 35 + val * 45;
const sat = 95;
const light = 58 + val * 28;
dot.style.background = `hsl(${hue}, ${sat}%, ${light}%)`;
const glowIntensity = 4 + val * 12;
const shadowColor = `hsl(${hue + 10}, 100%, 65%)`;
dot.style.boxShadow = `0 0 ${glowIntensity}px ${shadowColor}, 0 0 3px #ffcc88`;
if (val > 0.85) {
dot.style.boxShadow = `0 0 ${glowIntensity + 6}px #fff5b0, 0 0 6px #ffaa44`;
}
}
spectrumAnimationId = requestAnimationFrame(animate);
}
animate();
}
function togglePlayback() {
if (dom.audio.paused) {
dom.audio.play().catch(e => {});
} else {
dom.audio.pause();
}
updatePlayerUI();
}
function updatePlayerUI() {
state.isPlaying = !dom.audio.paused;
const vids = document.querySelectorAll('.zxx-slide-img');
var mState = () => {
vids.forEach(vid => audio.paused ? vid.pause(): vid.play() );
};
audio.onplaying = audio.onpause = () => mState();
if (state.isPlaying) {
startSpectrumAnimation();
updateProgressCircle();
centerBtn.title = "暂停";
} else {
if (spectrumAnimationId) cancelAnimationFrame(spectrumAnimationId);
spectrumAnimationId = null;
centerBtn.title = "播放";
}
}
function getAngleFromEvent(e, rect) {
const cx = rect.left + rect.width / 2, cy = rect.top + rect.height / 2;
let clientX = e.touches ? e.touches.clientX : e.clientX, clientY = e.touches ? e.touches.clientY : e.clientY;
const dx = clientX - cx, dy = clientY - cy;
let angle = Math.atan2(dy, dx);
if(angle < 0) angle += 2 * Math.PI;
let progressAngle = angle - Math.PI/2;
if(progressAngle < 0) progressAngle += 2 * Math.PI;
return progressAngle / (2 * Math.PI);
}
function seekByEvent(e, rect) {
const progress = getAngleFromEvent(e, rect);
if(!dom.audio.duration) return;
dom.audio.currentTime = progress * dom.audio.duration;
updateProgressCircle();
}
function bindCircularProgressEvents() {
const p = dom.spectrumPlayer;
let d = false;
const m = (e) => { if(!d) return; e.preventDefault(); seekByEvent(e, p.getBoundingClientRect()); };
const u = () => { d = false; document.removeEventListener('mousemove', m); document.removeEventListener('mouseup', u); };
p.addEventListener('mousedown', (e) => {
if(e.target === dom.centerBtn || dom.centerBtn.contains(e.target)) return;
e.preventDefault(); d = true;
seekByEvent(e, p.getBoundingClientRect());
document.addEventListener('mousemove', m);
document.addEventListener('mouseup', u);
});
p.addEventListener('touchstart', (e) => {
if(e.target === dom.centerBtn || dom.centerBtn.contains(e.target)) return;
e.preventDefault(); d = true;
seekByEvent(e, p.getBoundingClientRect());
document.addEventListener('touchmove', m);
document.addEventListener('touchend', u);
});
p.addEventListener('click', (e) => {
if(e.target === dom.centerBtn || dom.centerBtn.contains(e.target)) return;
seekByEvent(e, p.getBoundingClientRect());
});
}
function initPlayer() {
dom.progressCircle.style.strokeDashoffset = circumference;
updateDotGeometry();
rebuildSpectrumDots();
bindCircularProgressEvents();
dom.centerBtn.addEventListener('click', (e) => { e.stopPropagation(); togglePlayback(); });
dom.audio.addEventListener('timeupdate', updateProgressCircle);
dom.audio.addEventListener('play', updatePlayerUI);
dom.audio.addEventListener('pause', updatePlayerUI);
}
initPlayer();
papa.oncontextmenu = (e) => e.preventDefault();
let fs = true;
let fsTimer;
fullscreen.onclick = () => {
if(fs){
fullscreen.innerText = '退出全屏';
papa.requestFullscreen();
}else{
fullscreen.innerText = '全屏欣赏';
document.exitFullscreen();
}
fs = !fs;
};
papa.addEventListener('mousemove', () => {
clearTimeout(fsTimer);
fullscreen.style.opacity = '1';
fsTimer = setTimeout(() => {
fullscreen.style.opacity = '0';
}, 3000);
});
</script>
漂亮,谢谢分享 欣赏精美佳作!向醉美老师学习! klxf 发表于 2026-5-28 23:21
漂亮,谢谢分享
谢谢友友分享! 夕阳西下 发表于 2026-5-29 08:28
欣赏精美佳作!向醉美老师学习!
夕阳友友客气了!
页:
[1]