假如世界没有你
本帖最后由 亚伦影音工作室 于 2026-3-15 19:22 编辑 <br /><br /><style>#bj {position: relative;
width: 1286px;
height: 720px;
margin-left: -300px;
margin-top: 10px;
overflow: hidden;z-index:12345;
background:url(https://pic1.imgdb.cn/item/6862641f58cb8da5c87f852b.jpg),linear-gradient(135deg, #e56420, #c22525, #3d9c31, #000078);
}
#lyricsCanvas {
position: absolute;
top: 30%;
left: 2%;
width: 800px;
height: 450px;
z-index: 2;
}
.controls-containe{
position: absolute;
bottom: 30px;
left: 10px;
width: 100%;
display: flex;
justify-content: center;
}
.controls {
width: 85%;
display: flex;
align-items: center;
gap: 10px;
z-index: 4;
}
#progress {position:relative;
bottom: 8px;
flex-grow: 1;
width: 100%;
height: 4px;
-webkit-appearance: none;
background-color: transparent;
outline: none;
}
#progress::-webkit-slider-container {
height: 18px;border-radius: 20px;
overflow: hidden;
}
#progress::-webkit-slider-runnable-track {
height: 4px;border-radius: 20px;
background: #EEE;
}
#progress::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 12px;
height: 12px;
border-radius: 20px;
background: #880000;
border: 1px solid transparent;
margin-top: -4px;
border-image: linear-gradient(#880000,#880000) 0 fill / 4 11 4 0 / 0px 0px 0 2000px;
}
.play-btn {
width: 90px;
height: 30px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
background-color: transparent;
border: none;
cursor: pointer;
font: 400 24px '华文隶书', sans-serif;
color: #eee;
display: flex;
align-items: center;
justify-content: center;
}
.time-display {
font: 300 20px '华文隶书', sans-serif;
color: #eee;
min-width: 110px;
text-align: center;
}
</style>
<divid="bj">
<canvas id="lyricsCanvas" width="850" height="450"></canvas>
<div class="controls-containe">
<div class="controls">
<span id="playBtn" class="play-btn">暂停</span>
<input type="range" id="progress" min="0" max="100" value="0"></input>
<span id="timeDisplay" class="time-display">00:00 / 00:00</span>
</div>
</div>
</div>
<audio id="audio" src="https://s2.cldisk.com/sv-w8/audio/65/45/bb/3b5c023645788fee48a8e13f62d7573c/audio.mp3" autoplay loop></audio>
<script>
// 基础工具函数:时间格式化
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs < 10 ? '0' + secs : secs}`;
}
// 时间显示更新函数
function updateTimeDisplay() {
const currentTime = audio.currentTime;
const duration = audio.duration || 0;
timeDisplay.textContent = `${formatTime(currentTime)} / ${formatTime(duration)}`;
}
// DOM元素获取
const dom = {
lyricsCanvas: document.getElementById('lyricsCanvas'),
playBtn: document.getElementById('playBtn'),
progress: document.getElementById('progress'),
timeDisplay: document.getElementById('timeDisplay')
};
const lyricsCtx = dom.lyricsCanvas.getContext('2d');
// LRC歌词数据
const lrcText = `
今夜微风轻送
把我的心吹动
多少尘封的往日情
重回到我心中
往事随风飘送
把我的心刺痛
你是那美梦难忘记
深藏在记忆中
总是要经历百转和千回
才知情深意浓
总是要走遍千山和万水
才知何去何从
为何等到错过多年以后
才明白自己最真的梦
是否还记得我
还是已忘了我
今夜微风轻轻送
吹散了我的梦
今夜微风轻送
把我的心吹动
多少尘封的往日情
重回到我心中
往事随风飘送
把我的心刺痛
你是那美梦难忘记
深藏在记忆中
总是要历经百转和千回
才知情深意浓
总是要走遍千山和万水
才知何去何从
为何等到错过多年以后
才明白自己最真的梦
是否还记得我
还是已忘了我
今夜微风轻轻送
吹散了我的梦
`;
//解析LRC歌词
function parseLRC() {
return lrcText.split('\n')
.filter(line => line.trim() && line.includes('['))
.map(line => {
const timeMatch = line.match(/\[(\d+):(\d+)\.(\d+)\]/);
if (!timeMatch) return null;
const time = parseInt(timeMatch) * 60 + parseInt(timeMatch) + parseInt(timeMatch)/100;
const text = line.replace(/\[.*?\]/g, '').trim();
return text ? { time, text } : null;
})
.filter(item => item)
.sort((a, b) => a.time - b.time);
}
const lyricsList = parseLRC();
let currentLyricIndex = -1;
let floatingLyrics = [];
class FloatingLyric {
constructor(text) {
this.text = text;
this.x = Math.random() * (dom.lyricsCanvas.width - 100);
this.y = Math.random() * (dom.lyricsCanvas.height - 30);
this.vx = (Math.random() - 0.5) * 0.5;
this.vy = (Math.random() - 0.5) * 0.5;
this.opacity = 0;
this.targetOpacity = 0.8 + Math.random() * 0.2;
this.size = 30 + Math.random() * 7;
this.color = `hsl(${Math.random() * 60}, 100%, 70%)`;
this.life = 0;
this.maxLife = 10;
this.fadeInDuration = 1;
this.fadeOutDuration = 2;
this.isActive = true;
lyricsCtx.font = `${this.size}px 微软雅黑`;
this.textWidth = lyricsCtx.measureText(this.text).width;
}
update(deltaTime) {
this.life += deltaTime;
this.x += this.vx;
this.y += this.vy;
if (this.x < 10) {
this.x = 10;
this.vx *= -0.8;
} else if (this.x + this.textWidth > dom.lyricsCanvas.width - 10) {
this.x = dom.lyricsCanvas.width - this.textWidth - 10;
this.vx *= -0.8;
}
if (this.y < this.size + 10) {
this.y = this.size + 10;
this.vy *= -0.8;
} else if (this.y > dom.lyricsCanvas.height - 10) {
this.y = dom.lyricsCanvas.height - 10;
this.vy *= -0.8;
}
if (this.life < this.fadeInDuration) {
this.opacity = (this.life / this.fadeInDuration) * this.targetOpacity;
} else if (this.life > this.maxLife - this.fadeOutDuration) {
this.opacity = ((this.maxLife - this.life) / this.fadeOutDuration) * this.targetOpacity;
} else {
this.opacity = this.targetOpacity;
}
}
draw() {
if (this.opacity <= 0) return;
lyricsCtx.save();
lyricsCtx.globalAlpha = this.opacity;
lyricsCtx.font = `${this.size}px 微软雅黑`;
lyricsCtx.fillStyle = '#000';
for (let i = 1; i <= 3; i++) {
lyricsCtx.fillText(this.text, this.x + i, this.y + i);
}
lyricsCtx.fillStyle = this.color;
lyricsCtx.fillText(this.text, this.x, this.y);
lyricsCtx.shadowBlur = 10;
lyricsCtx.shadowColor = this.color;
lyricsCtx.shadowOffsetX = 0;
lyricsCtx.shadowOffsetY = 0;
lyricsCtx.restore();
}
startFadeOut() {
this.maxLife = this.life + this.fadeOutDuration;
this.isActive = false;
}
}
// 最后一句歌词特殊处理
class LastLyric {
constructor(text) {
this.text = text;
this.opacity = 0;
this.size = 30;
this.color = "#ff0000";
this.isActive = false;
this.fadeInDuration = 2;
this.fadeOutDuration = 2;
this.life = 0;
this.maxLife = 30;
}
update(deltaTime) {
this.life += deltaTime;
if (!this.isActive) {
this.opacity = 0;
return;
}
if (this.life < this.fadeInDuration) {
this.opacity = (this.life / this.fadeInDuration);
} else if (this.life > this.maxLife - this.fadeOutDuration) {
this.opacity = ((this.maxLife - this.life) / this.fadeOutDuration);
if (this.opacity <= 0) {
this.deactivate();
}
} else {
this.opacity = 1;
}
}
draw() {
if (!this.isActive || this.opacity <= 0) return;
lyricsCtx.save();
lyricsCtx.globalAlpha = this.opacity;
lyricsCtx.font = `bold ${this.size}px 微软雅黑`;
lyricsCtx.textAlign = 'center';
lyricsCtx.textBaseline = '10';
lyricsCtx.fillStyle = '#000';
lyricsCtx.fillText(this.text, dom.lyricsCanvas.width / 2 + 2, dom.lyricsCanvas.height / 2 + 2);
lyricsCtx.fillStyle = this.color;
lyricsCtx.fillText(this.text, dom.lyricsCanvas.width / 2, dom.lyricsCanvas.height / 2);
lyricsCtx.shadowBlur = 15;
lyricsCtx.shadowColor = this.color;
lyricsCtx.restore();
}
activate() {
this.isActive = true;
this.life = 0;
this.opacity = 0;
}
deactivate() {
this.isActive = false;
this.opacity = 0;
this.life = 0;
}
}
const lastLyric = new LastLyric("欢迎回到我这里");
let isLastLyricActive = false;
//核心动画循环
let lastTime = 0;
function animate(timestamp) {
if (audio.paused) {
requestAnimationFrame(animate);
return;
}
const deltaTime = (timestamp - lastTime) / 1000;
lastTime = timestamp;
lyricsCtx.clearRect(0, 0, dom.lyricsCanvas.width, dom.lyricsCanvas.height);
const currentAudioTime = audio.currentTime;
let targetLyricIndex = -1;
for (let i = 0; i < lyricsList.length; i++) {
if (currentAudioTime >= lyricsList.time) {
targetLyricIndex = i;
} else {
break;
}
}
if (targetLyricIndex !== -1 && targetLyricIndex !== currentLyricIndex) {
if (targetLyricIndex !== lyricsList.length - 1) {
lastLyric.deactivate();
isLastLyricActive = false;
}
const targetLyric = lyricsList;
if (targetLyricIndex === lyricsList.length - 1) {
lastLyric.activate();
isLastLyricActive = true;
} else {
const newLyric = new FloatingLyric(targetLyric.text);
const nextLyricTime = lyricsList?.time || (audio.duration || currentAudioTime + 5);
newLyric.maxLife = nextLyricTime - targetLyric.time + 1;
floatingLyrics.push(newLyric);
}
currentLyricIndex = targetLyricIndex;
}
floatingLyrics = floatingLyrics.filter(lyric => {
lyric.update(deltaTime);
lyric.draw();
return lyric.life < lyric.maxLife && lyric.opacity > 0.01;
});
lastLyric.update(deltaTime);
lastLyric.draw();
if (audio.duration) {
const progressPercent = (audio.currentTime / audio.duration) * 100;
dom.progress.value = progressPercent;
updateTimeDisplay();
}
requestAnimationFrame(animate);
}
// 播放/暂停按钮事件
dom.playBtn.addEventListener('click', () => {
if (audio.paused) {
audio.play().then(() => {
dom.playBtn.textContent = '暂停';
if (isLastLyricActive) {
lastLyric.deactivate();
isLastLyricActive = false;
}
lastTime = performance.now();
requestAnimationFrame(animate);
}).catch(e => console.error('音频播放失败:', e));
} else {
audio.pause();
dom.playBtn.textContent = '播放';
}
});
// 进度条拖动事件
dom.progress.addEventListener('input', () => {
if (!audio.duration) return;
const targetTime = (dom.progress.value / 100) * audio.duration;
audio.currentTime = targetTime;
currentLyricIndex = -1;
floatingLyrics = [];
lastLyric.deactivate();
isLastLyricActive = false;
updateTimeDisplay();
let targetLyricIndex = -1;
for (let i = 0; i < lyricsList.length; i++) {
if (targetTime >= lyricsList.time) {
targetLyricIndex = i;
} else {
break;
}
}
if (targetLyricIndex !== -1) {
const targetLyric = lyricsList;
if (targetLyricIndex === lyricsList.length - 1) {
lastLyric.activate();
isLastLyricActive = true;
} else {
const newLyric = new FloatingLyric(targetLyric.text);
newLyric.life = targetTime - targetLyric.time;
const nextLyricTime = lyricsList?.time || (audio.duration || targetTime + 5);
newLyric.maxLife = nextLyricTime - targetLyric.time + 1;
if (newLyric.life > newLyric.maxLife) {
newLyric.startFadeOut();
}
floatingLyrics.push(newLyric);
}
}
dom.playBtn.textContent = audio.paused ? '播放' : '暂停';
});
// 音频结束事件
audio.addEventListener('ended', () => {
audio.currentTime = 0;
audio.play();
dom.playBtn.textContent = '暂停';
currentLyricIndex = -1;
floatingLyrics = [];
lastLyric.deactivate();
isLastLyricActive = false;
lastTime = performance.now();
requestAnimationFrame(animate);
});
// 音频加载完成事件
audio.addEventListener('loadedmetadata', updateTimeDisplay);
// 初始化自动播放
audio.play().then(() => {
dom.playBtn.textContent = '暂停';
lastTime = performance.now();
requestAnimationFrame(animate);
}).catch(() => {
console.log('自动播放被阻止,请点击播放按钮开始');
dom.timeDisplay.textContent = '00:00 / --:--';
});
</script> 这个词同步很特别,好看。欣赏亚伦老师好帖{:4_199:} 欣赏老师的代码音画,点赞!
亚纶这个歌词走动效果可以去微风论坛看看最近新进去的那个了了的代码,感觉他的歌词游动效果漂亮一点 看看是差不多的,反正歌词不要挡住人物 http://www.llz123.net/llz/llz/mulu/tongnian/playlist.html
页:
[1]