亚伦影音工作室 发表于 2026-3-29 19:17

玩倒影

本帖最后由 亚伦影音工作室 于 2026-3-30 09:08 编辑 <br /><br /><style>
@import url("https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap");
#papa {margin:30px 0;left:calc(50% - 81px);transform:translateX(-50%);width: 1286px;height: 720px;background:#000 url("") no-repeat center/cover;position: relative;z-index: 1;overflow: hidden;font-family: "Ma Shan Zheng","SimHei", "Arial", "sans-serif";--state:running;}
#tu{ width: 100%;left:35%;top: 0%;position: absolute;
      height: 100%; transform: perspective(800px) rotateY(150deg)rotatex(0deg);background:url(https://img4.oldkids.cn/upload/2020/10/23/photo_20201023221718179.jpg)no-repeat center/cover;
    }
.lyricDisp{transition:.5s all ease;text-align:center;color:#000;filter:drop-shadow(#fff 1px 0 0)drop-shadow(#fff 0 1px 0)drop-shadow(#fff -1px 0 0) drop-shadow(#fff 0 -1px0);line-height: 50px;--bg:linear-gradient(90deg, #000078, #ff0000, #000, #800000, #ff0000);margin: 0;padding: 0;}
.lyricDisp.highlight{font-size:1.5em;color:#00aa00;--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:15%;top: 25%;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 -50px -webkit-gradient(linear, 0 0, 0 120%, from(transparent), color-stop(.1, 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: ;transform: perspective(300px) rotateY(50deg)rotatex(0deg)}
#player {position: absolute;top: 85%;right: 45%;width: 60px;height: 60px;cursor: pointer;animation: starfish-rotate 3s linear infinite;transform-origin: center;transform-style: preserve-3d;transform: rotateZ(0deg);transition: transform 0.3s ease;z-index: 100;}
@keyframes starfish-rotate {to {transform:rotateZ(360deg);}}
.stop #player{animation-play-state: paused;}

#fullscreen{position: absolute;border-radius: 4px;color:#00F5FF;background:#0000;box-shadow:0px 0px 0px 0px #fff;padding: 8px 8px;z-index: 90;font-size: 25px;font-weight: 100;opacity:0;border: none;cursor: pointer;top: 20px;left: 2%;}
#papa:hover #fullscreen { opacity:.8; }

#mplayer{position:absolute;text-align:center;top:95%;transform:translate(-50%);left:50%;z-index:60;font-size:18px;color:#FFf;}
#mplayer::before{position:absolute;content:attr(data-tt);left:0;bottom:25px;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="tu"></div>
<div id="testImg"><img id="player" src="https://638183.freep.cn/638183/small/780.webp" title="/" alt=""></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 id="fullscreen"></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.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.reflect.unpauseAnimations();
      document.getElementById('papa').style.setProperty('--bgd');
      }else{
      that.mObj.pause();
      that.image.classList.add('stop');
      that.reflect.pauseAnimations();
      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 = `
来生再和你相爱-烟嗓船长
曲:徐嘉良/词:未子夫
源码设计:了了子
代码改编:亚伦
歌词编辑:亚伦
亚伦影音工作室出品
离别站台 晚风吹过来
回忆涌入 脑海脑海
山盟海誓 化作了尘埃
泪在眼底 澎湃澎湃
彼岸花开花败又一载
我在奈何桥上等你回来
孟婆的碗 盛着前世的债
黄泉路上我也难以忘怀
如果今生 注定了分开
来世有缘 再和你相爱
蝴蝶它飞不过曾经沧海
我也戒不掉对你的依赖
如果今生 注定了分开
等下辈子我再拥你入怀
就算你走之后再没回来
岁月更替 我心不改
任春去秋来 人山与人海
你是我唯一 挚爱至爱
彼岸花开花败又一载
我在奈何桥上等你回来
孟婆的碗 盛着前世的债
黄泉路上我也难以忘怀
如果今生 注定了分开
来世有缘 再和你相爱
蝴蝶它飞不过曾经沧海
我也戒不掉对你的依赖
如果今生 注定了分开
等下辈子我再拥你入怀
就算你走之后再没回来
岁月更替 我心不改
任春去秋来 人山与人海
你是我唯一 挚爱至爱
`;
var opts = {
lrcDoc:lrctxt,
audioURL:"https://www.aaz.cx/plug/down.php?ac=music&lk=mp3&id=vxxvcvwss&.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>

杨帆 发表于 2026-3-29 19:45

好听的曲子,好靓的倒影,好美的玩法,谢谢亚伦老师精彩分享

如果能解决点击进度条歌词颤抖问题,效果会更完美~{:4_176:}

红影 发表于 2026-3-29 19:51

这样的倾斜歌词做倒影非常漂亮,欣赏亚伦老师好帖{:4_199:}

小文 发表于 2026-3-29 21:17

真好,欣赏了!谢谢!{:4_187:}

小辣椒 发表于 2026-3-30 22:08

欣赏亚纶好制作,那个图片转换效果小辣椒挺喜欢的,我也是玩了一次
页: [1]
查看完整版本: 玩倒影