feat: TurboSu initial release - racing telemetry dashboard

This commit is contained in:
Yei.J. (AskaEth)
2026-07-25 15:23:40 +08:00
commit d61bb61a83
61 changed files with 5270 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
{
"id": "tachometer",
"name": "转速仪表 - 转速表",
"category": "rpm",
"description": "赛车风格弧形转速表,支持红区换档提示,推荐横屏",
"author": "Yei.J. (AskaEth)",
"version": "1.0.0",
"config": {
"icon": "⏱️",
"max_rpm": 8000,
"redline": 7000,
"aspect_ratio": "16:9",
"render_mode": "contain"
}
}
+35
View File
@@ -0,0 +1,35 @@
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;font-family:'Segoe UI',system-ui,sans-serif;background:linear-gradient(135deg,#0a0a14,#1a1a30);">
<svg viewBox="0 0 300 200" width="90%" style="max-width:500px;">
<defs>
<linearGradient id="rpmGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#667eea"/>
<stop offset="40%" stop-color="#667eea"/>
<stop offset="70%" stop-color="#f39c12"/>
<stop offset="100%" stop-color="#e74c3c"/>
</linearGradient>
</defs>
<path d="M 50,170 A 100,100 0 0,1 250,170" fill="none" stroke="rgba(255,255,255,0.08)" stroke-width="18" stroke-linecap="round"/>
<path id="rpm-arc" d="M 50,170 A 100,100 0 0,1 250,170" fill="none" stroke="url(#rpmGrad)" stroke-width="18" stroke-linecap="round"
stroke-dasharray="314" stroke-dashoffset="314" style="transition:stroke-dashoffset 0.1s ease;"/>
<text x="150" y="150" text-anchor="middle" fill="#fff" font-size="48" font-weight="900" data-bind="rpm">0</text>
<text x="150" y="180" text-anchor="middle" fill="rgba(255,255,255,0.5)" font-size="14">RPM</text>
<text x="42" y="185" text-anchor="middle" fill="rgba(255,255,255,0.3)" font-size="10">0</text>
<text x="258" y="185" text-anchor="middle" fill="rgba(255,255,255,0.3)" font-size="10">8k</text>
</svg>
<div data-bind-rpm style="display:none;">
<script>
(function() {
const arc = document.getElementById('rpm-arc');
const observer = new MutationObserver(() => {
const rpm = parseFloat(getComputedStyle(document.querySelector('[data-bind-rpm]')).getPropertyValue('--rpm')) || 0;
const max = parseFloat(getComputedStyle(document.querySelector('[data-bind-rpm]')).getPropertyValue('--rpm-max')) || 8000;
if (!isNaN(rpm) && arc) {
const pct = Math.min(rpm / max, 1);
arc.setAttribute('stroke-dashoffset', 314 - (314 * pct));
}
});
observer.observe(document.querySelector('[data-bind-rpm]'), { attributes: true, attributeFilter: ['style'] });
})();
</script>
</div>
</div>