@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
|
||||
<title>TurboSu - 换挡灯</title>
|
||||
<style>
|
||||
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
|
||||
html,body{width:100%;height:100%;overflow:hidden;background:#0a0a0f;
|
||||
font-family:'SF Pro Display',-apple-system,system-ui,sans-serif}
|
||||
#root{width:100%;height:100%;display:flex;align-items:center;justify-content:center}
|
||||
#box{position:relative;overflow:hidden}
|
||||
#box.contain{max-width:100vw;max-height:100vh}
|
||||
#box.cover{min-width:100vw;min-height:100vh}
|
||||
#box.fill{width:100vw;height:100vh}
|
||||
#content{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:#0a0a0f;gap:min(2vw,8px);padding:min(2vh,12px)}
|
||||
.led{width:min(8vw,40px);height:min(12vw,60px);border-radius:4px;background:rgba(255,255,255,.03);transition:background .06s,box-shadow .06s}
|
||||
.led.on-green{background:#34C759;box-shadow:0 0 12px rgba(52,199,89,.5)}
|
||||
.led.on-yellow{background:#FF9F0A;box-shadow:0 0 16px rgba(255,159,10,.6)}
|
||||
.led.on-red{background:#E94634;box-shadow:0 0 24px rgba(233,70,52,.8)}
|
||||
.led.on-flash{animation:pulse .3s ease-in-out infinite alternate}
|
||||
@keyframes pulse{from{opacity:.7;box-shadow:0 0 24px rgba(233,70,52,.6)}to{opacity:1;box-shadow:0 0 40px rgba(255,50,30,1)}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"><div id="box" class="contain"><div id="content" id="led-strip"></div></div></div>
|
||||
<script>
|
||||
const M={aspect_ratio:"16:3",render_mode:"contain"};
|
||||
const N=12;
|
||||
(function(){
|
||||
const box=document.getElementById('box'),strip=document.getElementById('led-strip');
|
||||
const proto=location.protocol==='https:'?'wss:':'ws:',wsUrl=proto+'//'+location.host+'/ws';
|
||||
let ws,rt,leds=[];
|
||||
|
||||
function pr(r){if(!r||r==='auto')return null;const p=r.split(':');if(p.length===2)return +p[0]/+p[1]}
|
||||
|
||||
for(let i=0;i<N;i++){const d=document.createElement('div');d.className='led';strip.appendChild(d);leds.push(d)}
|
||||
|
||||
function apply(){
|
||||
const rt=pr(M.aspect_ratio||'16:3'),md=M.render_mode||'contain';
|
||||
if(!rt){box.style.width='100vw';box.style.height='100vh';box.className='fill';return}
|
||||
const vw=window.innerWidth,vh=window.innerHeight,vr=vw/vh;let cw,ch;
|
||||
if(md==='cover'){cw=vw;ch=vw/rt;box.className='cover'}
|
||||
else{box.className='contain';cw=vr>rt?vh*rt:vw;ch=vr>rt?vh:vw/rt}
|
||||
box.style.width=cw+'px';box.style.height=ch+'px'
|
||||
}
|
||||
|
||||
function cn(){ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}}
|
||||
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);if(m.type==='telemetry'){
|
||||
const rpm=m.data.rpm||0,max=m.data.max_rpm||8000,pct=rpm/max;
|
||||
const greenEnd=Math.floor(N*.55),yellowEnd=Math.floor(N*.8);
|
||||
for(let i=0;i<N;i++){
|
||||
const t=i/N,cls=['led'];
|
||||
if(t<=pct){
|
||||
if(i>=yellowEnd)cls.push('on-red','on-flash');
|
||||
else if(i>=greenEnd)cls.push('on-yellow');
|
||||
else cls.push('on-green');
|
||||
}
|
||||
leds[i].className=cls.join(' ');
|
||||
}
|
||||
}}catch(e){}};ws.onclose=()=>{rt=setTimeout(cn,2000)}}
|
||||
|
||||
apply();window.addEventListener('resize',apply);cn()
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "shift_light",
|
||||
"name": "换挡指示灯",
|
||||
"category": "racing",
|
||||
"description": "转速接近红线区逐级亮灯闪烁提示",
|
||||
"author": "Yei.J. (AskaEth)",
|
||||
"version": "1.0.0",
|
||||
"supported_games": "all",
|
||||
"config": {
|
||||
"icon": "💡",
|
||||
"aspect_ratio": "16:3",
|
||||
"render_mode": "contain"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user