跟随夏风游山河
<meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>跟随夏风游山河</title>
<link href="https://fonts.googleapis.com/css2?family=Liu+Jian+Mao+Cao&family=Long+Cang&family=Ma+Shan+Zheng&family=ZCOOL+KuaiLe&family=ZCOOL+QingKe+HuangYou&display=swap" rel="stylesheet">
<link rel="preload" href="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/b07eaa5abe451a7d019ec16fb09dbcf5_preview.webp" as="image">
<style>
#papa{position:relative;display:grid;place-items:center;margin:30px 0;width:1280px;height:750px;left:calc(50% - 81px);transform:translateX(-50%);box-shadow:3px 3px 6px gray;overflow:hidden;z-index:1;background:var(--bg1);--bg1:#000 url('https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/6733cdf1900c745a119d57e49ff0d2d4_preview.webp') no-repeat 50% 25%/cover;--bg2:#000 url('https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/b07eaa5abe451a7d019ec16fb09dbcf5_preview.webp') no-repeat 50% 25%/cover;font-family:"ZCOOL KuaiLe","Ma Shan Zheng","Long Cang","华文行楷","SimHei","Arial","sans-serif";--state:running;}
#LRCShow{position:absolute;top:10%;left:50%;transform:translate(-50%,calc(-50% - 20px));width:70%;height:180px;z-index:3;display:flex;align-items:center;justify-content:center;filter:drop-shadow(0 4px 25px rgba(0,20,30,0.7));pointer-events:none;}
.lyricDisp{position:relative;font:58px/1.5 'Long Cang','ZCOOL KuaiLe','Ma Shan Zheng','Microsoft YaHei','华文隶书','KaiTi',cursive;font-weight:400;white-space:nowrap;transition:0.2s;width:fit-content;max-width:100%;transform-origin:center center;animation:yaoSoft 1.6s ease-in-out infinite alternate;margin:0;letter-spacing:4px;color:transparent;-webkit-text-stroke:0.8px rgba(255,255,255,0.35);text-stroke:0.8px rgba(255,255,255,0.35);text-align:center;}
.lyricDisp.paused{animation-play-state:paused !important;}
@keyframes yaoSoft{0%{transform:perspective(600px) rotateX(-10deg) rotateY(10deg) scale(1.05) translateY(-3px);}100%{transform:perspective(600px) rotateX(10deg) rotateY(-10deg) scale(0.95) translateY(3px);}}
.lyricDisp::before{position:absolute;content:attr(data-lrc);width:0;height:100%;left:0;top:0;color:transparent;background:linear-gradient(90deg,#FF6B6B 15%,#FFD93D 30%,#6BCB77 45%,#4D96FF 60%,#9B59B6 75%,#FF6B6B 90%);-webkit-background-clip:text;background-clip:text;overflow:hidden;white-space:nowrap;animation:var(--aniName) var(--durTime) linear forwards;animation-play-state:var(--aniPlayState);pointer-events:none;-webkit-text-stroke:0.8px rgba(255,255,255,0.35);text-stroke:0.8px rgba(255,255,255,0.35);}
.lyricDisp.paused::before{animation-play-state:paused !important;}
@keyframes bgMove1{from{width:0;}to{width:100%;}}
@keyframes bgMove0{from{width:0;}to{width:100%;}}
.prog{position:absolute;left:30px;bottom:30px;width:300px;height:2px;background:rgba(255,255,255,0.3);cursor:pointer;z-index:20;--prog:0%;border-radius:2px;}
.prog .fill{position:absolute;left:0;top:0;height:100%;width:var(--prog);background:linear-gradient(90deg,#6BCB77,#4D96FF);border-radius:2px;box-shadow:0 0 15px rgba(75,200,120,0.3);transition:width 0.08s linear;}
.prog .time-display{position:absolute;bottom:12px;left:50%;transform:translateX(-50%);font-size:18px;font-family:'Consolas',monospace;color:rgba(255,255,255,0.55);letter-spacing:1px;white-space:nowrap;text-shadow:0 0 10px rgba(0,0,0,0.8);}
#playBtnImg{position:absolute;right:35px;bottom:32px;width:95px;height:95px;border-radius:50%;cursor:pointer;box-shadow:0 0 20px rgba(255,200,200,0.2);border:2px solid rgba(255,255,255,0.25);transition:transform 0.2s,border-color 0.2s;z-index:20;animation:rotate 8s linear infinite var(--state);pointer-events:auto;}
#playBtnImg:hover{transform:scale(1.08);border-color:rgba(255,215,0,0.4);}
#playBtnImg:active{transform:scale(0.92);}
#lrcContent0{display:none;}
.pd-vid{position:absolute;width:100%;height:100%;object-fit:cover;mask:linear-gradient(45deg,red 88%,transparent 90%);-webkit-mask:linear-gradient(45deg,red 88%,transparent 90%);mix-blend-mode:screen;z-index:1;pointer-events:none;}
#canvas{position:relative;top:15%;left:-45%;transform:translateX(45%);cursor:pointer;}
@media (max-width:1300px){#playerCore{width:96vw;height:90vh;border-radius:16px;}.lyricDisp{font-size:32px;}#LRCShow{width:75%;height:150px;}}
@media (max-width:820px){.lyricDisp{font-size:26px;letter-spacing:2px;}#LRCShow{width:80%;height:130px;}}
@media (max-width:480px){.lyricDisp{font-size:18px;letter-spacing:1px;}#LRCShow{width:85%;height:100px;}}
#fullscreen{border-radius:4px;position:absolute;color:DarkGray;padding:4px 8px;z-index:12;font-size:25px;border:none;cursor:pointer;top:25px;left:25px;background:transparent;}
#fullscreen:hover{font-style:italic;}
.myCanvas{position:absolute;z-index:5;left:calc(50% + 80px);transform:translateX(-50%);bottom:-130px;animation:scale 12s ease infinite alternate var(--state);}
@keyframes scale{0%{transform:translateX(-50%) perspective(800px) rotateY(0deg) scale(0.01);}20%{transform:translateX(-50%) perspective(800px) rotateY(0deg) scale(1);}40%{transform:translateX(-50%) perspective(800px) rotateY(-25deg) scale(1.2);}60%{transform:translateX(-50%) perspective(800px) rotateY(25deg) scale(1.2);}80%{transform:translateX(-50%) perspective(800px) rotateY(0deg) scale(1);}100%{transform:translateX(-50%) perspective(800px) rotateY(0deg) scale(0.01);}}
@keyframes rotate{from{transform:rotate(0);}to{transform:rotate(360deg);}}
</style>
</head>
<body>
<div id="papa">
<canvas class="myCanvas" width="800" height="400"></canvas>
<canvas id="canvas" width="300" height="300"></canvas>
<div id="fullscreen">全屏欣赏</div>
<video class="pd-vid" src="https://img2.tukuppt.com/video_show/15653652/00/80/83/60d04564c32f7.mp4" autoplay loop muted></video>
<div id="LRCShow"></div>
<div class="prog" id="prog">
<div class="fill" id="progFill"></div>
<div class="time-display" id="timeDisplay">00:00 / 00:00</div>
</div>
<img id="playBtnImg" src="https://s41.ax1x.com/2026/07/08/pmriFQ1.png" alt=" " />
<textarea id='lrcContent0'></textarea>
</div>
<script>
var songData = {
title: '跟随夏风游山河',
audio: 'https://www.joy127.com/url/155130.mp3',
lrc: `跟随夏风游山河-晨夕之家
演唱:晨夕之家
且随清风
先把心放松
LRC编辑:醉美水芙蓉
跟随夏风游山河
一步一景都从容
闲游山河心里暖
不慌不忙见彩虹
假日时光慢慢过
自在随心笑春风
跟随夏风游山河
一路都是好风景
背上行囊轻轻走
看云开在远山头
不敢路也不回头
把欢喜装进衣袖
人道半身更懂得
慢一点才是丰收
把日子过成暖流
把笑意留在眼眸
跟随夏风游山河
一步一景都从容
闲游山河心里暖
不慌不忙见彩虹
假日时光慢慢过
自在随心笑春风
跟随夏风游山河
一路都是好风景
路过溪水河老桥
听鸟鸣在树哨飘
不问明天有多少
只管今天多逍遥
人到半生更懂得
慢一点才是丰收
把日子过成暖流
把笑意留在眼眸
跟随夏风游山河
一步一景都从容
闲游山河心里暖
不慌不忙见彩虹
假日时光慢慢过
自在随心笑春风
跟随夏风游山河
一路都是好风景
看一眼青山心就困了
停一阵风声脚步轻了
把疲惫交给远方
把自在带在身旁
跟随夏风游山河
一步一景都从容
闲游山河心里暖
不慌不忙见彩虹
假日时光慢慢过
自在随心笑春风
跟随夏风游山河
一路都是好风景
谢谢欣赏!
`
};
var lrcPlayer = function() {
return this.init.apply(this, arguments);
};
lrcPlayer.prototype = {
constructor: lrcPlayer,
init: function(opts) {
this.lyricTxtObj = document.getElementById(opts.lrcTxtID);
var lyricTxt = this.lyricTxtObj.value;
this.showLrcObj = document.getElementById(opts.lrcShowID);
this.showLrcObj.innerHTML = '';
this.gcline = document.createElement('div');
this.gcline.className = 'lyricDisp';
this.showLrcObj.appendChild(this.gcline);
this.audioCtrl = document.getElementById(opts.audioCtrl);
this.progressInfo = document.getElementById('timeDisplay');
this.lrcVec = this.parseLrc(lyricTxt);
console.log('歌词条目总数:', this.lrcVec.length);
this.genPlayer(opts.audioURL);
this.isPlaying = false;
return this;
},
parseLrc: function(lyricTxt) {
var lines = lyricTxt.split('\n');
var result = [];
for (var i = 0; i < lines.length; i++) {
var line = lines;
var timeMatch = line.match(/^\[(\d{2}):(\d{2})\.(\d{2})\]/);
if (timeMatch) {
var minutes = parseInt(timeMatch);
var seconds = parseInt(timeMatch);
var milliseconds = parseInt(timeMatch);
var time = minutes * 60 + seconds + milliseconds / 100;
var text = line.replace(timeMatch, '').trim();
if (text) result.push({ time: time, text: text });
}
}
result.sort(function(a, b) { return a.time - b.time; });
return result;
},
resetLyrics: function() {
this.idx = 0;
if (this.lrcVec && this.lrcVec.length > 0) {
var text = this.lrcVec.text || ' ';
this.gcline.innerHTML = text;
this.gcline.setAttribute('data-lrc', text);
this.gcline.style.setProperty('--aniName', 'bgMove0');
this.gcline.style.setProperty('--durTime', '2000ms');
this.gcline.style.setProperty('--aniPlayState', 'running');
}
},
showLrc: function(durTime) {
if (this.idx >= this.lrcVec.length) return;
var text = this.lrcVec.text;
if (text.length === 0) text = ' ';
this.gcline.innerHTML = text;
this.gcline.setAttribute('data-lrc', text);
this.gcline.style.setProperty('--aniName', 'bgMove' + (this.idx % 2));
var finalDur = Math.max(durTime * 0.7, 600);
finalDur = Math.min(finalDur, 3000);
this.gcline.style.setProperty('--durTime', finalDur + 'ms');
this.gcline.style.setProperty('--aniPlayState', 'running');
},
genPlayer: function(mUrl) {
var that = this;
this.mObj = document.createElement("audio");
this.mObj.loop = true;
this.mObj.muted = false;
this.mObj.src = mUrl;
this.showLrcObj.appendChild(this.mObj);
this.idx = 0;
this.mObj.addEventListener('loadedmetadata', function() {
if (that.lrcVec.length > 0) {
var text = that.lrcVec.text || ' ';
that.gcline.innerHTML = text;
that.gcline.setAttribute('data-lrc', text);
that.gcline.style.setProperty('--aniName', 'bgMove0');
that.gcline.style.setProperty('--durTime', '2000ms');
that.gcline.style.setProperty('--aniPlayState', 'running');
that.idx = 0;
}
});
this.mObj.addEventListener('ended', function() {
that.idx = 0;
that.isPlaying = false;
that.audioCtrl.classList.remove('playing');
that.gcline.style.setProperty('--aniPlayState', 'paused');
that.resetLyrics();
that.mObj.play().catch(function() {});
that.resetLyrics();
that.mObj.play().catch(function() {});
syncAllUIState();
});
var vid = document.querySelector('video');
const bg1 = getComputedStyle(papa).getPropertyValue('--bg1');
const bg2 = getComputedStyle(papa).getPropertyValue('--bg2');
this.mObj.addEventListener('playing', function() {
that.isPlaying = true;
if (vid && vid.paused) vid.play().catch(function() {});
papa.style.setProperty('--state', 'running');
papa.style.background = bg1;
that.audioCtrl.classList.add('playing');
that.gcline.style.setProperty('--aniPlayState', 'running');
if (this.currentTime < 0.5 && that.idx > 0) {
that.idx = 0;
that.resetLyrics();
}
that.gcline.classList.remove('paused');
syncAllUIState();
});
this.mObj.addEventListener('pause', function() {
that.isPlaying = false;
if (vid && !vid.paused) vid.pause();
papa.style.setProperty('--state', 'paused');
papa.style.background = bg2;
that.audioCtrl.classList.remove('playing');
that.gcline.style.setProperty('--aniPlayState', 'paused');
that.gcline.classList.add('paused');
syncAllUIState();
});
var lastUpdateTime = 0;
this.mObj.addEventListener('timeupdate', function() {
var now = Date.now();
if (now - lastUpdateTime < 100) return;
lastUpdateTime = now;
var current = this.currentTime || 0;
var duration = this.duration || 0;
if (duration > 0) {
var min = Math.floor(current / 60);
var sec = Math.floor(current % 60);
var min2 = Math.floor(duration / 60);
var sec2 = Math.floor(duration % 60);
that.progressInfo.textContent =
String(min).padStart(2, '0') + ':' + String(sec).padStart(2, '0') +
' / ' +
String(min2).padStart(2, '0') + ':' + String(sec2).padStart(2, '0');
var pct = (current / duration) * 100;
document.getElementById('progFill').style.width = Math.min(pct, 100) + '%';
document.getElementById('prog').style.setProperty('--prog', Math.min(pct, 100) + '%');
}
if (that.idx < that.lrcVec.length - 1) {
var nextTime = that.lrcVec.time;
if (this.currentTime >= nextTime - 0.2) {
that.idx++;
var dur = (that.lrcVec.time - that.lrcVec.time) * 950;
dur = Math.max(dur * 0.7, 600);
dur = Math.min(dur, 3000);
that.showLrc(dur);
}
}
});
this.audioCtrl.onclick = function(e) {
e.stopPropagation();
if (that.mObj.paused) {
that.mObj.play().catch(function(err) {
console.log('播放失败:', err);
});
} else {
that.mObj.pause();
}
};
var progEl = document.getElementById('prog');
progEl.addEventListener('click', function(e) {
e.stopPropagation();
var rect = this.getBoundingClientRect();
var ratio = (e.clientX - rect.left) / rect.width;
var target = Math.max(0, Math.min(1, ratio)) * that.mObj.duration;
if (!isNaN(target) && isFinite(target)) {
that.mObj.currentTime = target;
var idx = 0;
for (var i = 0; i < that.lrcVec.length; i++) {
if (target >= that.lrcVec.time) idx = i;
else break;
}
that.idx = idx;
if (that.lrcVec.length > 0 && that.idx < that.lrcVec.length) {
var text = that.lrcVec.text || ' ';
that.gcline.innerHTML = text;
that.gcline.setAttribute('data-lrc', text);
that.gcline.style.setProperty('--aniName', 'bgMove' + (that.idx % 2));
that.gcline.style.setProperty('--durTime', '1500ms');
that.gcline.style.setProperty('--aniPlayState', 'running');
}
syncAllUIState();
}
});
setTimeout(function() {
that.mObj.play().catch(function(err) {
console.log('自动播放被拦截,点击按钮播放:', err);
});
}, 500);
},
stopMusic: function() {
this.mObj.pause();
this.isPlaying = false;
this.audioCtrl.classList.remove('playing');
},
setAudioUrl: function(mUrl) {
this.mObj.src = mUrl;
},
reStart: function() {
this.idx = 0;
this.mObj.currentTime = 0;
this.mObj.play().catch(function() {});
},
isMusicEnd: function() {
return this.mObj.ended;
}
};
var opts = {
lrcTxtID: 'lrcContent0',
lrcShowID: "LRCShow",
audioURL: songData.audio,
audioCtrl: 'playBtnImg'
};
document.getElementById('lrcContent0').value = songData.lrc;
var player = new lrcPlayer(opts);
console.log('歌词同步模块加载完成,点击底部按钮播放');
const canvas1 = document.querySelector('.myCanvas');
const ctx = canvas1.getContext('2d');
ctx.save();
ctx.font = 'bold 66px 华文隶书,Microsoft YaHei';
ctx.strokeStyle = "rgb(0,191,255)";
ctx.lineWidth = 1;
ctx.textAlign = 'left';
ctx.strokeText("跟随夏风游山河", 130,200);
ctx.restore();
const canvas = document.getElementById("canvas");
let angle = 0;
let animationId = null;
function syncAllUIState() {
const audio = player.mObj;
if (!audio) return;
playBtnImg.title = audio.paused ? "播放" : "暂停";
canvas.title = audio.paused ?"播放" : "暂停";
if (audio.paused) {
stopAnimation();
} else {
if (!animationId) draw();
}
}
function draw() {
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(angle);
ctx.scale(0.8,0.8);
for (let i = 0; i < 12; i++) {
ctx.save();
let hue = (360 / 12) * i;
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
ctx.rotate(Math.PI * 2 / 12 * i);
ctx.fillRect(0, 0, 100, 2);
ctx.beginPath();
var radgrad2 = ctx.createRadialGradient(0, 105, 0, 0, 105, 10);
radgrad2.addColorStop(0.03, "red");
radgrad2.addColorStop(0.30, "lightgreen");
radgrad2.addColorStop(1, "darkred");
ctx.fillStyle = radgrad2;
ctx.arc(0, 110, 10, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
ctx.beginPath();
ctx.arc(0, 0, 10, 0, Math.PI * 2);
ctx.fillStyle = "rgba(248, 243, 235,0.8)";
ctx.fill();
ctx.restore();
angle -= 0.015;
animationId = requestAnimationFrame(draw);
}
function stopAnimation() {
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null;
}
}
canvas.onclick = (e) => {
e.stopPropagation();
playBtnImg.click();
};
const fullscreen = document.getElementById('fullscreen');
let fs = true,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', 2500);
});
document.addEventListener('visibilitychange', () => {
const audio = player.mObj;
if (!audio) return;
if (document.hidden) {
if (!audio.paused) audio.pause();
} else {
if (audio.paused && !audio.ended) audio.play().catch(() => {});
}
setTimeout(syncAllUIState, 50);
});
['contextmenu', 'dragstart', 'selectstart'].forEach(ev =>
papa.addEventListener(ev, (e) => { e.preventDefault(); })
);
playBtnImg.onanimationiteration = () => {
playBtnImg.style.setProperty('filter', `hue-rotate(${60 + Math.random() * 300}deg)`);
};
function init() {
draw();
setTimeout(syncAllUIState, 600);
}
init();
</script>
好听好看,谢谢友友精彩分享 klxf 发表于 2026-7-11 13:21
好听好看,谢谢友友精彩分享
谢谢友友光临!
页:
[1]