fix: composite dashboard RPM gauge - ╭ shape (left 90° arc + top straight line)
This commit is contained in:
@@ -48,7 +48,7 @@ html,body{width:100%;height:100%;overflow:hidden;background:#0a0a0f;color:#fff;
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"><div id="box" class="contain"><div id="content">
|
<div id="root"><div id="box" class="contain"><div id="content">
|
||||||
<div id="rpm-area"><svg id="rpm-svg" viewBox="0 0 640 440" preserveAspectRatio="xMidYMid meet"></svg></div>
|
<div id="rpm-area"><svg id="rpm-svg" viewBox="0 0 640 480" preserveAspectRatio="xMidYMid meet"></svg></div>
|
||||||
<div id="speed-area"><div id="speed-val">0</div><div id="speed-unit">KM/H</div></div>
|
<div id="speed-area"><div id="speed-val">0</div><div id="speed-unit">KM/H</div></div>
|
||||||
<div id="gear-area"><div id="gear-box"><span id="gear-val">1</span></div></div>
|
<div id="gear-area"><div id="gear-box"><span id="gear-val">1</span></div></div>
|
||||||
<div id="pedals">
|
<div id="pedals">
|
||||||
@@ -74,10 +74,62 @@ let GAME_ID='';
|
|||||||
const proto=location.protocol==='https:'?'wss:':'ws:',wsUrl=proto+'//'+location.host+'/ws';
|
const proto=location.protocol==='https:'?'wss:':'ws:',wsUrl=proto+'//'+location.host+'/ws';
|
||||||
let ws,rt,lR=-1,lG=-999;
|
let ws,rt,lR=-1,lG=-999;
|
||||||
|
|
||||||
const CX=320,CY=380,R=290,SA=-210,EA=-30;
|
const CX=300,CY=420,R=300,SA=180,EA=270;
|
||||||
|
|
||||||
function d2r(d){return d*Math.PI/180}
|
function d2r(d){return d*Math.PI/180}
|
||||||
function arcP(s,e,r){const sa=d2r(s),ea=d2r(e);return`M${CX+r*Math.cos(sa)} ${CY+r*Math.sin(sa)} A${r} ${r} 0 ${e-s>180?1:0} 1 ${CX+r*Math.cos(ea)} ${CY+r*Math.sin(ea)}`}
|
|
||||||
|
function drawRpm(cur,max,gear){
|
||||||
|
max=max||8000;cur=cur||0;
|
||||||
|
const sx=CX+R*Math.cos(d2r(SA)),sy=CY+R*Math.sin(d2r(SA)); // arc start
|
||||||
|
const ex=CX+R*Math.cos(d2r(EA)),ey=CY+R*Math.sin(d2r(EA)); // arc end -> top of arc
|
||||||
|
const lx=620,ly=ey; // straight line end (right side, same Y as arc top)
|
||||||
|
|
||||||
|
// arc length (90°) = 2πR * 90/360
|
||||||
|
const arcLen=Math.PI*R*90/360;
|
||||||
|
const lineLen=lx-ex;
|
||||||
|
const totalLen=arcLen+lineLen;
|
||||||
|
|
||||||
|
let h='';
|
||||||
|
// background: arc + line
|
||||||
|
h+=`<path d="M${sx},${sy} A${R},${R} 0 0 0 ${ex},${ey} L${lx},${ly}" fill="none" stroke="rgba(255,255,255,.04)" stroke-width="22" stroke-linecap="round" stroke-linejoin="round"/>`;
|
||||||
|
|
||||||
|
// scale marks on arc
|
||||||
|
for(let r=0;r<=max;r+=1000){
|
||||||
|
const pct=r/max;
|
||||||
|
const ang=SA+(EA-SA)*pct;
|
||||||
|
if(ang<=EA){
|
||||||
|
const a=d2r(ang);
|
||||||
|
const x1=CX+(R-18)*Math.cos(a),y1=CY+(R-18)*Math.sin(a);
|
||||||
|
const x2=CX+(R+18)*Math.cos(a),y2=CY+(R+18)*Math.sin(a);
|
||||||
|
const c=r>=max*0.85?'rgba(255,255,255,.12)':(r%2000===0?'rgba(255,255,255,.15)':'rgba(255,255,255,.05)');
|
||||||
|
h+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${c}" stroke-width="${r%2000===0?2:1}"/>`;
|
||||||
|
if(r%2000===0){
|
||||||
|
h+=`<text x="${CX+(R-34)*Math.cos(a)}" y="${CY+(R-34)*Math.sin(a)+4}" text-anchor="middle" font-size="10" fill="rgba(255,255,255,.2)">${r/1000}</text>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// progress
|
||||||
|
if(cur>0){
|
||||||
|
const pct=Math.min(cur/max,1);
|
||||||
|
if(pct<=arcLen/totalLen){
|
||||||
|
// progress within arc
|
||||||
|
const ap=pct*totalLen/arcLen;
|
||||||
|
const ang=SA+(EA-SA)*ap;
|
||||||
|
const px=CX+R*Math.cos(d2r(ang)),py=CY+R*Math.sin(d2r(ang));
|
||||||
|
h+=`<path d="M${sx},${sy} A${R},${R} 0 0 0 ${px},${py}" fill="none" stroke="#fff" stroke-width="22" stroke-linecap="round"/>`;
|
||||||
|
}else{
|
||||||
|
// full arc + partial line
|
||||||
|
const lp=(pct*totalLen-arcLen)/lineLen;
|
||||||
|
const px=ex+lp*(lx-ex);
|
||||||
|
h+=`<path d="M${sx},${sy} A${R},${R} 0 0 0 ${ex},${ey} L${px},${ly}" fill="none" stroke="#fff" stroke-width="22" stroke-linecap="round" stroke-linejoin="round"/>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h+=`<text x="${CX}" y="${CY-24}" text-anchor="middle" font-size="22" font-weight="200" fill="#fff">${Math.round(cur).toLocaleString()}</text>`;
|
||||||
|
h+=`<text x="${CX}" y="${CY+4}" text-anchor="middle" font-size="10" fill="rgba(255,255,255,.15)">×1000 rpm</text>`;
|
||||||
|
svg.innerHTML=h;
|
||||||
|
}
|
||||||
|
|
||||||
function parseRatio(r){if(!r||r==='auto')return null;const p=r.split(':');if(p.length===2){const w=+p[0],h=+p[1];return w/h}return null}
|
function parseRatio(r){if(!r||r==='auto')return null;const p=r.split(':');if(p.length===2){const w=+p[0],h=+p[1];return w/h}return null}
|
||||||
|
|
||||||
@@ -90,28 +142,6 @@ let GAME_ID='';
|
|||||||
box.style.width=cw+'px';box.style.height=ch+'px'
|
box.style.width=cw+'px';box.style.height=ch+'px'
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawRpm(cur,max,gear){
|
|
||||||
max=max||8000;cur=cur||0;
|
|
||||||
const ta=EA-SA,rd=max*0.85;
|
|
||||||
let h='';
|
|
||||||
h+=`<path d="${arcP(SA,EA,R)}" fill="none" stroke="rgba(255,255,255,.04)" stroke-width="22" stroke-linecap="round"/>`;
|
|
||||||
for(let r=0;r<=max;r+=1000){
|
|
||||||
const pct=r/max,ang=SA+ta*pct,a=d2r(ang);
|
|
||||||
const x1=CX+(R-20)*Math.cos(a),y1=CY+(R-20)*Math.sin(a);
|
|
||||||
const x2=CX+(R+20)*Math.cos(a),y2=CY+(R+20)*Math.sin(a);
|
|
||||||
const c=r>=rd?'rgba(255,255,255,.08)':(r%2000===0?'rgba(255,255,255,.12)':'rgba(255,255,255,.04)');
|
|
||||||
h+=`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${c}" stroke-width="${r%2000===0?2:1}"/>`;
|
|
||||||
if(r%2000===0)h+=`<text x="${CX+(R-36)*Math.cos(a)}" y="${CY+(R-36)*Math.sin(a)+4}" text-anchor="middle" font-size="10" fill="rgba(255,255,255,.2)">${r/1000}</text>`;
|
|
||||||
}
|
|
||||||
if(cur>0){
|
|
||||||
const pct=Math.min(cur/max,1),eA=SA+ta*pct;
|
|
||||||
h+=`<path d="${arcP(SA,eA,R)}" fill="none" stroke="#fff" stroke-width="22" stroke-linecap="round"/>`;
|
|
||||||
}
|
|
||||||
h+=`<text x="${CX}" y="${CY-12}" text-anchor="middle" font-size="24" font-weight="200" fill="#fff">${Math.round(cur).toLocaleString()}</text>`;
|
|
||||||
h+=`<text x="${CX}" y="${CY+14}" text-anchor="middle" font-size="11" fill="rgba(255,255,255,.2)">×1000 rpm</text>`;
|
|
||||||
svg.innerHTML=h;
|
|
||||||
}
|
|
||||||
|
|
||||||
function connect(){
|
function connect(){
|
||||||
ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}}
|
ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}}
|
||||||
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);
|
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);
|
||||||
|
|||||||
Reference in New Issue
Block a user