醉美水芙蓉 发表于 前天 20:50

【水芙蓉播放器】风雨天涯

<style>@import url("https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap");
#papa{position: relative;margin: 30px 0px;display: grid;place-items: center;width: 1300px;height: 720px;left: calc(50% - 81px);transform: translateX(-50%);box-shadow: 3px 3px 6px gray;overflow: hidden;z-index: 10000;background: #0000 ;font-family: "Ma Shan Zheng","华文行楷","SimHei", "Arial", "sans-serif";
}
#gradient {position: absolute;margin: 0px 0px;
width: 100%;z-index: 1;
height: 100%;transform: scale(1.1);
background:url(https://img-baofun.zhhainiao.com/fs/scene/preview_img_raw/48fc8dfae65ca5e332393f69cfd02d3f.jpg) no-repeat 0 0px/cover,linear-gradient(122deg,#880000, #aa6600, #3d9c31, #000090);
filter: url(#water);
      background-blend-mode:overlay, difference, normal, lighten ;
   
}

#dt {position: absolute;margin: 0px 0px;
width: 100%;mix-blend-mode:lighten ;z-index: 2;
height: 100%;}
#dt img{
width: 100%;
height: 100%;}
.lyricDisp{transition:.5s all ease;text-align:center;color:#fff000;filter:drop-shadow(#000 1px 0 0)drop-shadow(#000 0 1px 0)drop-shadow(#000 -1px 0 0) drop-shadow(#000 0 -1px0);line-height: 50px;--bg:linear-gradient(90deg, #00aa00, #ff0000, #00ff00, #800000, #ff0000);margin: 0;padding: 0;}
.lyricDisp.highlight{font-size:1.5em;color:#00cc00;--aniName:bgMove1;--durTime:100ms;--aniPlayState:running;}
.lyricDisp.highlight::before{position:absolute;content:attr(data-lrc);width:10%;height:100%;color:transparent;overflow:hidden;white-space:nowrap;animation:var(--aniName) var(--durTime) linear forwards;animation-play-state:var(--aniPlayState);background: var(--bg);-webkit-background-clip: text;text-align:left;}
@keyframes bgMove1{from{width:0%;}to{width:100%;}}@keyframes bgMove0{from{width:0%}to{width:100%;}}
.LRCShow{position:absolute;left:8%;top: 20%;width:53%;height: 30%;font-weight:390;font-size:1.6em;z-index: 9;display: flex;flex-direction: column;justify-content: center;align-items: center;gap: 2px;-webkit-box-reflect: below -15% -webkit-gradient(linear, 0 0, 0 120%, from(transparent), color-stop(.0, transparent), to(rgba(3,3,3,1)));
    background: -webkit-linear-gradient(top, rgba(174,188,191,1) 0%,rgba(110,119,116,1) 50%,rgba(10,14,10,1) 51%,rgba(10,8,9,1) 100%);
    -webkit-background-clip: text;-webkit-text-fill-color: ;}
#player {position: absolute;top: 76%;right: 43%;width: 140px;
height: 140px;
display: grid;cursor:pointer;
        place-items: center;animation: starfish-rotate 3s linear infinite;transform-origin: center;transform-style: preserve-3d;transition: transform 0.3s ease;z-index: 100;}
@keyframes starfish-rotate {to {transform:rotateZ(360deg);}}
#rect {position: absolute;
        display: grid;
        place-items: center;
width:35%;
height: 35%;
clip-path: polygon(60% 0, 100% 0, 50% 50%, 40% 100%, 0 100%, 50% 50%);

}

#rect:nth-of-type(1) { background:#5500ff;transform: rotate(0deg);
}
#rect:nth-of-type(2) { background:#ff0000;transform: rotate(45deg);
}
#rect:nth-of-type(3) { background:#00aa00;transform: rotate(90deg);
}
#rect:nth-of-type(4) { background:#fff000;transform: rotate(135deg);
}

.stop #player{animation-play-state: paused;}

#fullscreen{border-radius: 4px;position: absolute;
color:#fff;background:#0000;box-shadow:0px 0px 0px 0px #fff;
padding: 4px 8px;z-index: 120;
font-size: 25px;font-weight: 100;
border: none;
cursor: pointer;top: 5px;left: 8%;
}

#mplayer{position:absolute;text-align:center;top:95%;transform:translate(-50%);left:50%;z-index:100;font-size:18px;color:#7CFC00;}
#mplayer::before{position:absolute;content:attr(data-tt);left:0;bottom:23px;width:100%;text-align-last:justify;}
#mprog{width:500px;height:2px;accent-color:darkgreen;outline:none;cursor:pointer;}
#papa p {position: absolute;width: 50px;height: 350px;z-index: 3;left:8%;top: 25%;writing-mode: vertical-rl;text-orientation: upright;font: bold 4.5em/1.5 STLiti;letter-spacing: 30px;white-space: pre;color: #7CFC00; }

</style>
<div id="papa">
<div id="fullscreen">全屏欣赏</div>
<svg width="0" height="0" id="reflect">
<filter id="water">
    <feTurbulence type="fractalNoise" baseFrequency=".05 .01" numOctaves="1" result="noise1"></feTurbulence>
    <feColorMatrix in="noise1" type="hueRotate" values="0" result="noise2">
      <animate attributeName="values" from="0" to="360" dur="1s" repeatCount="indefinite"/>
    </feColorMatrix>
    <feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="7" in="SourceGraphic" in2="noise2" />
</filter>
</svg>
<div id="gradient"></div>
<div id="dt"> <img src="https://img2.oldkids.cn/upload/2026/04/06/photo_0_20260406153610799.gif"id="IMGb" /></div>

<div id="testImg"><div id="player"title="暂停/播放" >
<spanid="rect"></span>
<spanid="rect"></span>
<spanid="rect"></span>
<spanid="rect"></span>
</div>
</div>
<div id="mplayer" data-tt="00:00 00:00"><input id="mprog" type="range" min="0" max="100" step="any" value="0" title=""/></div>

<div class="LRCShow"></div>

</div>

<script type="text/javascript">
var lrcPlayerM=function(){return this.init.apply(this,arguments)};
lrcPlayerM.prototype={
constructor:lrcPlayerM,
init:function(opts){
    this.showLrcObj=document.querySelector('.LRCShow');
    this.player=document.getElementById('player');
    this.image=document.getElementById('testImg');
    this.reflect=document.getElementById('reflect');
this.imageb= document.getElementById("IMGb");

    this.gclines=new Array();
    this.slines=typeof opts.showLines==='number'?opts.showLines:1;
    this.midLineIdx = Math.floor(this.slines / 2);
    for(k=0;k<this.slines;k++){
      this.gclines=document.createElement('div');
      this.gclines.className='lyricDisp';
      if(k === this.midLineIdx) this.gclines.classList.add('highlight');
      this.showLrcObj.appendChild(this.gclines)
    }
    this.handleLrc(opts.lrcDoc);
    this.genPlayer(opts.audioURL)
},
handleLrc:function(lyricTxt){
    this.lrcVec=new Array();
    var lyriclist=lyricTxt.split(/\r|\n|\r\n/);
    for(n=0;n<lyriclist.length;n++){
      chkTime=lyriclist.match(/\[\d{1,2}:\d{2}.\d{1,3}\]|\[\d{1,2}:\d{2}\]/g);
      if(chkTime){
      tIdx=lyriclist.lastIndexOf(']');
      if(tIdx>0)lrcTxt=lyriclist.substr(tIdx+1);
      for(m=0;m<chkTime.length;m++){
          ta=chkTime.substr(1).replace(']','').split(/:/);
          _t=(+ta)*60+(+ta);
          if(this.lrcVec.length==0&&_t!=0){this.lrcVec.push()}
          this.lrcVec.push()
      }
      }
    }
    this.lrcVec.sort(function(a,b){return(a-b)})
},
showLrc:function(durTime){
    this.gclines.innerHTML=this.gclines.dataset.lrc=this.lrcVec.length>0?this.lrcVec:"\u3000";
    this.gclines.style.setProperty('--aniName','bgMove'+(this.idx%2));
    this.gclines.style.setProperty('--durTime',durTime+'ms');
    this.gclines.style.setProperty('--aniPlayState','running')
},
genPlayer:function(mUrl){
    this.mObj=document.createElement("audio");
    this.mObj.loop=false;
    this.mObj.muted=false;
    this.mObj.src=mUrl;
    this.mObj.id = 'bgMusic';
    this.mObj.playsinline = true;   
    this.mObj.setAttribute('webkit-playsinline', 'true');
    this.showLrcObj.appendChild(this.mObj);
    this.idx=0;
    var that=this;
    this.mObj.addEventListener('ended',function(){that.idx=0;this.play()});
    this.mObj.addEventListener('playing',function(){that.gclines.style.setProperty('--aniPlayState','running')});
    this.mObj.addEventListener('pause',function(){that.gclines.style.setProperty('--aniPlayState','paused')});
    this.mObj.addEventListener('error',function(){console.log("audio wrong, remove play start event");that.showLrcObj.style.display='none';that.showLrcObj.removeChild(this)});
    this.mObj.addEventListener('timeupdate',function(){
      if(that.idx>=that.lrcVec.length)return;
      if(this.currentTime>that.lrcVec){
      if(that.idx<(that.lrcVec.length-1)){
          that.showLrc((that.lrcVec-that.lrcVec)*950)
      }else{
          that.showLrc((this.duration-that.lrcVec)*950)
      }
      for(let n = 0; n < that.slines; n++){
          if(n === that.midLineIdx) continue;
          let offset = n - that.midLineIdx;
          let lrcIndex = that.idx + offset;
          if(lrcIndex < 0 || lrcIndex >= that.lrcVec.length){
            that.gclines.innerHTML = "\u3000";
          }else{
            that.gclines.innerHTML = that.lrcVec || "\u3000";
          }
      }
      that.idx++
      }
    });
    this.player.onclick=function(){
      if(that.mObj.paused){
      that.mObj.play();
      that.image.classList.remove('stop');
that.imageb.play();
      that.reflect.unpauseAnimations();
      document.getElementById('papa').style.setProperty('--bgd');
      }else{
      that.mObj.pause();
      that.image.classList.add('stop');
      that.reflect.pauseAnimations();
that.imageb.stop();
      document.getElementById('papa').style.setProperty('--bgd');
      }
    };
    try{this.mObj.play()}catch(err){console.log(err.message)}
},
stopMusic:function(){this.mObj.pause();this.mObj.controls=false;},
setAudioUrl:function(mUrl){this.mObj.src=mUrl},
isMusicEnd:function(){return this.mObj.ended},
reStart:function(){this.idx=0;this.mObj.play()}
}
let lrctxt = `
风雨天涯(女版)
词:歌奴(尹庆全)
曲:歌奴(尹庆全)
LRC编辑:醉美水芙蓉
演唱:江念念
寒雨连绵丝丝凉
风卷落叶绕身旁
遥望远方路漫长
雨泪滑落湿衣裳
星月无光夜凄凉
天光无影心迷茫
恍惚梦中旧模样
思乡滋味在心房
风雨天涯泪涟涟
风啸声声过千山
孤身漂泊天地间
归期遥遥路漫漫
星月无光夜凄凉
天光无影心迷茫
恍惚梦中旧模样
思乡滋味在心房
风雨天涯路漫长
风载乡愁飘四方
天涯万里风雨狂
梦里牵挂从未放
风雨天涯望星光
风拂归程念故乡
心揣着梦不彷徨
风雨天涯向远方
风雨天涯向远方
☆★谢谢欣赏★☆
`;
var opts = {
lrcDoc:lrctxt,
audioURL:"https://mpimg.cn/view.php/a992cbecfb52de744330ce8d5adc52f8.mp3",
showLines:3,
};
var lrcPlayer = new lrcPlayerM(opts);
const fullscreen = document.getElementById('fullscreen');
let fs = true;
      fullscreen.onclick = () => {
            if (fs) {
                fullscreen.innerText = '退出全屏';
               papa.requestFullscreen();
            } else {
                fullscreen.innerText = '全屏欣赏';
                document.exitFullscreen();
            }
            fs = !fs;
      };
['contextmenu', 'dragstart','selectstart'].forEach(type =>
document.getElementById('papa').addEventListener(type, e => e.preventDefault()));
player.onanimationiteration = () => player.style.setProperty('filter', `hue-rotate(${0 + Math.random() * 270}deg)`);
const audio = document.getElementById('bgMusic') || lrcPlayer.mObj;
const mplayer = document.getElementById('mplayer');
const mprog = document.getElementById('mprog');
var mseek = false;
let toMin = (val) => {
if(!val) return '00:00';
val = Math.floor(val);
let min = parseInt(val / 60),sec = parseFloat(val % 60);
if(min < 10) min = '0' + min;
if(sec < 10) sec = '0' + sec;
return min + ':' + sec;
}
function findLrcIndexByTime(audioTime, lrcVec) {
for (let i = lrcVec.length - 1; i >= 0; i--) {
    if (lrcVec <= audioTime) {
      return i;
    }
}
return 0;
}
audio.addEventListener('loadedmetadata', () => {
mplayer.dataset.tt = toMin(0) + ' ' + toMin(audio.duration);
});
audio.addEventListener('timeupdate', () => {
if(!audio.duration) return;
if(!mseek) mprog.value = (audio.currentTime / audio.duration) * 100;
mplayer.dataset.tt = toMin(audio.currentTime) + ' ' + toMin(audio.duration);
});
mprog.onmousedown = () => mseek = true;
mprog.onmouseup = () => mseek = false;
mprog.onchange = () => {
if (!audio.duration) return;
const targetTime = (mprog.value / 100) * audio.duration;
audio.currentTime = targetTime;
const targetIdx = findLrcIndexByTime(targetTime, lrcPlayer.lrcVec);
lrcPlayer.idx = targetIdx;
let durTime = 0;
if (targetIdx < lrcPlayer.lrcVec.length - 1) {
    durTime = (lrcPlayer.lrcVec - lrcPlayer.lrcVec) * 950;
} else {
    durTime = (audio.duration - lrcPlayer.lrcVec) * 950;
}
lrcPlayer.showLrc(durTime);
for (let n = 0; n < lrcPlayer.slines; n++) {
    if (n === lrcPlayer.midLineIdx) continue;
    let offset = n - lrcPlayer.midLineIdx;
    let lrcIndex = targetIdx + offset;
    if (lrcIndex < 0 || lrcIndex >= lrcPlayer.lrcVec.length) {
      lrcPlayer.gclines.innerHTML = "\u3000";
    } else {
      lrcPlayer.gclines.innerHTML = lrcPlayer.lrcVec || "\u3000";
    }
}
};
mprog.oninput = () => {
if(!audio.duration) return;
let currentTime = (mprog.value / 100) * audio.duration;
mplayer.dataset.tt = toMin(currentTime) + ' ' + toMin(audio.duration);
lrcPlayer.idx = 0;
for(let line of lrcPlayer.gclines){
    line.innerHTML = "\u3000";
}
};
</script>

<script>
if ('getContext' in document.createElement('canvas')) {
    HTMLImageElement.prototype.play = function() {
      if (this.storeCanvas) {
            // 洢canvas
            this.storeCanvas.parentElement.removeChild(this.storeCanvas);
            this.storeCanvas = null;
            //
               imageb.style.opacity = '';
      }
      if (this.storeUrl) {
            this.src = this.storeUrl;   
      }
    };
    HTMLImageElement.prototype.stop = function() {
      var canvas = document.createElement('canvas');
      //
      var width = this.width, height = this.height;
      if (width && height) {
            // 洢
            if (!this.storeUrl) {
                this.storeUrl = this.src;
            }
            // canvasС
            canvas.width = width;
            canvas.height = height;
            //
            canvas.getContext('2d').drawImage(this, 0, 0, width, height);
            //
            try {
                this.src = canvas.toDataURL("image/gif");
            } catch(e) {
                //
                this.removeAttribute('src');
                // canvas
                canvas.style.position = 'absolute';
                //
                this.parentElement.insertBefore(canvas, this);
                //
                this.style.opacity = '0';
                // 洢canvas
                this.storeCanvas = canvas;
            }
      }
    };
}


var imageb= document.getElementById("IMGb");

</script>

绿蔷薇 发表于 前天 20:56

撒花花
芙蓉晚上好
{:9_269:}

绿蔷薇 发表于 前天 20:57

这款同步歌词还有倒影~~{:4_123:}

绿蔷薇 发表于 前天 21:00

好听,嗓音高亢带一点沧桑感
蛐蛐好有画面感,勾勒出一幅天涯风雨的场景

绿蔷薇 发表于 前天 21:01

渐变色运用的真好,播放器漂亮,同步歌词制作的精准又好看~~

绿蔷薇 发表于 前天 21:01

芙蓉制作辛苦了
谢谢带来精美的音乐帖
{:5_130:}

念若莲 发表于 昨天 10:38

绿蔷薇 发表于 2026-4-22 20:57
这款同步歌词还有倒影~~

咦果然,破薇细心{:9_286:}

念若莲 发表于 昨天 10:39

真好听哦,播放器好看嘀{:9_272:}

醉美水芙蓉 发表于 昨天 12:09

绿蔷薇 发表于 2026-4-22 21:01
芙蓉制作辛苦了
谢谢带来精美的音乐帖

谢谢友友支持!

醉美水芙蓉 发表于 昨天 12:09

念若莲 发表于 2026-4-23 10:39
真好听哦,播放器好看嘀

谢谢友友支持!
页: [1] 2 3
查看完整版本: 【水芙蓉播放器】风雨天涯