假如世界没有你
本帖最后由 亚伦影音工作室 于 2025-10-5 13:35 编辑 <br /><br /><style>#bj {position: relative;
width: 1286px;
height: 720px;
margin-left: -300px;
margin-top: 10px;
overflow: hidden;z-index:12345;
background:radial-gradient(ellipse farthest-corner at center center, transparent 38%,#000 90%),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://hs6.krakenfiles.com/uploads/03-10-2025/5fhsb3r441/music.m4a" 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 = "#fff666";
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]