GUI
This commit is contained in:
@@ -172,6 +172,14 @@
|
||||
<button class="act-btn subtle full" onclick="setImuNorth()">Aktuelle Richtung als Norden setzen</button>
|
||||
<button class="act-btn subtle full" onclick="setImuLevel()">Aktuelle Neigung als Null setzen</button>
|
||||
</div>
|
||||
<div class="sr">
|
||||
<span class="sr-led led-off"></span>
|
||||
<span class="sr-key">HUD-Farbe</span>
|
||||
<span class="sr-val" style="display:flex;align-items:center;gap:6px;">
|
||||
<input type="color" id="hud_color_picker" value="#00ff91" style="width:32px;height:22px;border:none;background:none;cursor:pointer;padding:0;" oninput="applyHudColorFromAdmin(this.value)" onchange="applyHudColorFromAdmin(this.value)">
|
||||
<button class="act-btn subtle" style="padding:2px 8px;font-size:11px;" onclick="resetHudColor()">Reset</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sr">
|
||||
<span class="sr-led led-off"></span>
|
||||
<span class="sr-key">Hinweis</span>
|
||||
@@ -2820,6 +2828,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var h = localStorage.getItem('hudHexColor');
|
||||
if (h) {
|
||||
var el = document.getElementById('hud_color_picker');
|
||||
if (el) el.value = '#' + h;
|
||||
}
|
||||
} catch(e) {}
|
||||
})();
|
||||
|
||||
function applyHudColorFromAdmin(cssColor) {
|
||||
var hex = cssColor.replace('#', '');
|
||||
try { localStorage.setItem('hudHexColor', hex); } catch(e) {}
|
||||
}
|
||||
|
||||
function resetHudColor() {
|
||||
var el = document.getElementById('hud_color_picker');
|
||||
if (el) el.value = '#00ff91';
|
||||
applyHudColorFromAdmin('#00ff91');
|
||||
}
|
||||
|
||||
async function setImuNorth() {
|
||||
if (!window.confirm('Rover jetzt wirklich sauber nach Norden ausgerichtet?')) return;
|
||||
setAdminStatus('Speichere Nordrichtung...');
|
||||
|
||||
+3
-2
@@ -281,10 +281,11 @@ header {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: calc(270px * var(--cam-scale));
|
||||
height: calc(270px * var(--cam-scale));
|
||||
width: calc(405px * var(--cam-scale));
|
||||
height: calc(405px * var(--cam-scale));
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
filter: drop-shadow(0 0 1.5px rgba(0,0,0,.9)) drop-shadow(0 0 3px rgba(0,0,0,.6));
|
||||
}
|
||||
@keyframes xh-spin { to { transform: rotate(360deg); } }
|
||||
@keyframes xh-pulse {
|
||||
|
||||
+79
-48
@@ -94,7 +94,7 @@
|
||||
S: <span id="overlay-distance">0,00</span> m
|
||||
</div>
|
||||
<div class="c-xhair">
|
||||
<svg viewBox="-110 -110 220 220" xmlns="http://www.w3.org/2000/svg" width="220" height="220">
|
||||
<svg viewBox="-110 -110 220 220" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
|
||||
<!-- outer rotating dashed ring -->
|
||||
<circle class="xh-rot" cx="0" cy="0" r="103" fill="none" stroke="rgba(0,255,145,.14)" stroke-width="1" stroke-dasharray="4 13"/>
|
||||
<!-- roll arc (static) r=96, ±60° from top -->
|
||||
@@ -158,8 +158,8 @@
|
||||
<line x1="-42" y1="-72" x2="42" y2="-72" stroke="rgba(0,255,145,.35)" stroke-width=".5"/>
|
||||
<text id="imu-heading-text" x="0" y="-62.5" fill="rgba(0,255,145,.92)" font-size="9" text-anchor="middle" letter-spacing="1">HDG 000° N</text>
|
||||
<!-- roll / pitch readouts -->
|
||||
<text id="imu-roll-text" x="-73" y="76" fill="rgba(0,255,145,.82)" font-size="7.5" text-anchor="middle">R +0.0°</text>
|
||||
<text id="imu-pitch-text" x="73" y="76" fill="rgba(0,255,145,.82)" font-size="7.5" text-anchor="middle">P +0.0°</text>
|
||||
<text id="imu-roll-text" x="-73" y="76" fill="rgba(0,255,145,.82)" font-size="10.5" text-anchor="middle">R +0.0°</text>
|
||||
<text id="imu-pitch-text" x="73" y="76" fill="rgba(0,255,145,.82)" font-size="10.5" text-anchor="middle">P +0.0°</text>
|
||||
</g>
|
||||
<!-- center dot -->
|
||||
<circle cx="0" cy="0" r="3" fill="rgba(0,255,145,.92)"/>
|
||||
@@ -167,7 +167,6 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="c-scanlines"></div>
|
||||
<div class="c-vignette"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -329,6 +328,26 @@ var imuOverlayState = {
|
||||
lastUpdateAt: 0
|
||||
};
|
||||
|
||||
var hudRGB = [0, 255, 145];
|
||||
var xhairSvgOrigHTML = null;
|
||||
|
||||
function hudRgba(alpha) {
|
||||
return 'rgba(' + hudRGB[0] + ',' + hudRGB[1] + ',' + hudRGB[2] + ',' + alpha + ')';
|
||||
}
|
||||
|
||||
function applyHudColor(hex) {
|
||||
var r = parseInt(hex.slice(0, 2), 16);
|
||||
var g = parseInt(hex.slice(2, 4), 16);
|
||||
var b = parseInt(hex.slice(4, 6), 16);
|
||||
if (isNaN(r) || isNaN(g) || isNaN(b)) return;
|
||||
hudRGB = [r, g, b];
|
||||
try { localStorage.setItem('hudHexColor', hex); } catch (e) {}
|
||||
var svgEl = document.querySelector('.c-xhair svg');
|
||||
if (!svgEl) return;
|
||||
if (!xhairSvgOrigHTML) xhairSvgOrigHTML = svgEl.innerHTML;
|
||||
svgEl.innerHTML = xhairSvgOrigHTML.replace(/rgba\(0,255,145,/g, 'rgba(' + r + ',' + g + ',' + b + ',');
|
||||
}
|
||||
|
||||
function setText(id, text) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) {
|
||||
@@ -357,7 +376,7 @@ function formatSignedNumber(value, digits) {
|
||||
}
|
||||
|
||||
function headingToCompass(deg) {
|
||||
var dirs = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"];
|
||||
var dirs = ["N","NNO","NO","ONO","O","OSO","SO","SSO","S","SSW","SW","WSW","W","WNW","NW","NNW"];
|
||||
return dirs[Math.round(((deg % 360) + 360) % 360 / 22.5) % 16];
|
||||
}
|
||||
|
||||
@@ -1141,12 +1160,14 @@ function drawImuHorizonOverlay(context, canvasWidth, canvasHeight, size) {
|
||||
context.save();
|
||||
context.translate(cx, cy);
|
||||
context.rotate(-rollRad);
|
||||
context.shadowColor = "rgba(0,0,0,.85)";
|
||||
context.shadowBlur = 3;
|
||||
context.beginPath();
|
||||
context.moveTo(0, -90 * unit);
|
||||
context.lineTo(-5.5 * unit, -79 * unit);
|
||||
context.lineTo(5.5 * unit, -79 * unit);
|
||||
context.closePath();
|
||||
context.fillStyle = "rgba(0,255,145,.88)";
|
||||
context.fillStyle = hudRgba(.88);
|
||||
context.fill();
|
||||
context.restore();
|
||||
|
||||
@@ -1155,6 +1176,8 @@ function drawImuHorizonOverlay(context, canvasWidth, canvasHeight, size) {
|
||||
context.translate(cx, cy);
|
||||
context.rotate(-rollRad);
|
||||
context.translate(0, pitchOffsetPx);
|
||||
context.shadowColor = "rgba(0,0,0,.85)";
|
||||
context.shadowBlur = 2.5;
|
||||
|
||||
[
|
||||
{ y: -33, span: 11, op: .28 }, { y: 33, span: 11, op: .28 },
|
||||
@@ -1164,12 +1187,12 @@ function drawImuHorizonOverlay(context, canvasWidth, canvasHeight, size) {
|
||||
context.beginPath();
|
||||
context.moveTo(-pl.span * unit, pl.y * unit);
|
||||
context.lineTo(pl.span * unit, pl.y * unit);
|
||||
context.strokeStyle = "rgba(0,255,145," + pl.op + ")";
|
||||
context.strokeStyle = hudRgba(pl.op);
|
||||
context.lineWidth = 0.9 * unit;
|
||||
context.stroke();
|
||||
});
|
||||
|
||||
context.strokeStyle = "rgba(0,255,145,.95)";
|
||||
context.strokeStyle = hudRgba(.95);
|
||||
context.lineWidth = 2.8 * unit;
|
||||
context.beginPath(); context.moveTo(-60 * unit, 0); context.lineTo(60 * unit, 0); context.stroke();
|
||||
context.beginPath(); context.moveTo(-60 * unit, 0); context.lineTo(-52 * unit, -5 * unit); context.stroke();
|
||||
@@ -1181,13 +1204,15 @@ function drawImuHorizonOverlay(context, canvasWidth, canvasHeight, size) {
|
||||
var bw = 84 * unit, bh = 15 * unit;
|
||||
context.fillStyle = "rgba(0,15,8,.65)";
|
||||
context.fillRect(cx - bw / 2, cy - 72 * unit, bw, bh);
|
||||
context.shadowColor = "rgba(0,0,0,.9)";
|
||||
context.shadowBlur = 3;
|
||||
context.font = (9 * unit) + 'px "Consolas","Cascadia Mono",monospace';
|
||||
context.fillStyle = "rgba(0,255,145,.92)";
|
||||
context.fillStyle = hudRgba(.92);
|
||||
context.textAlign = "center";
|
||||
context.textBaseline = "middle";
|
||||
context.fillText("HDG " + String(Math.round(headingDeg)).padStart(3, "0") + "° " + headingToCompass(headingDeg), cx, cy - 62.5 * unit);
|
||||
context.font = (7.5 * unit) + 'px "Consolas","Cascadia Mono",monospace';
|
||||
context.fillStyle = "rgba(0,255,145,.72)";
|
||||
context.font = (10.5 * unit) + 'px "Consolas","Cascadia Mono",monospace';
|
||||
context.fillStyle = hudRgba(.82);
|
||||
context.fillText("R " + formatSignedNumber(rollDeg, 1) + "°", cx - 73 * unit, cy + 76 * unit);
|
||||
context.fillText("P " + formatSignedNumber(pitchDeg, 1) + "°", cx + 73 * unit, cy + 76 * unit);
|
||||
context.restore();
|
||||
@@ -1198,67 +1223,76 @@ function drawCrosshairOverlayToCanvas(context, canvasWidth, canvasHeight, size)
|
||||
var cy = canvasHeight / 2;
|
||||
var unit = size / 180;
|
||||
|
||||
function circle(radius, stroke, lineWidth, dash) {
|
||||
function circle(radius, alpha, lineWidth, dash) {
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.arc(cx, cy, radius * unit, 0, Math.PI * 2);
|
||||
if (dash) context.setLineDash(dash.map(function (value) { return value * unit; }));
|
||||
context.strokeStyle = stroke;
|
||||
context.shadowColor = "rgba(0,0,0,.85)";
|
||||
context.shadowBlur = 2.5;
|
||||
context.strokeStyle = hudRgba(alpha);
|
||||
context.lineWidth = lineWidth * unit;
|
||||
context.stroke();
|
||||
context.restore();
|
||||
}
|
||||
|
||||
function line(x1, y1, x2, y2, stroke, lineWidth) {
|
||||
function line(x1, y1, x2, y2, alpha, lineWidth) {
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.moveTo(cx + (x1 * unit), cy + (y1 * unit));
|
||||
context.lineTo(cx + (x2 * unit), cy + (y2 * unit));
|
||||
context.strokeStyle = stroke;
|
||||
context.shadowColor = "rgba(0,0,0,.85)";
|
||||
context.shadowBlur = 2.5;
|
||||
context.strokeStyle = hudRgba(alpha);
|
||||
context.lineWidth = lineWidth * unit;
|
||||
context.stroke();
|
||||
context.restore();
|
||||
}
|
||||
|
||||
function path(points, stroke, lineWidth) {
|
||||
function path(points, alpha, lineWidth) {
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.moveTo(cx + (points[0][0] * unit), cy + (points[0][1] * unit));
|
||||
for (var i = 1; i < points.length; i += 1) {
|
||||
context.lineTo(cx + (points[i][0] * unit), cy + (points[i][1] * unit));
|
||||
}
|
||||
context.strokeStyle = stroke;
|
||||
context.shadowColor = "rgba(0,0,0,.85)";
|
||||
context.shadowBlur = 2.5;
|
||||
context.strokeStyle = hudRgba(alpha);
|
||||
context.lineWidth = lineWidth * unit;
|
||||
context.stroke();
|
||||
context.restore();
|
||||
}
|
||||
|
||||
circle(82, "rgba(0,255,145,.2)", 1, [4, 10]);
|
||||
circle(60, "rgba(0,255,145,.15)", 0.75, [2, 16]);
|
||||
circle(16, "rgba(0,255,145,.3)", 0.75);
|
||||
line(-86, 0, -19, 0, "rgba(0,255,145,.6)", 1);
|
||||
line(19, 0, 86, 0, "rgba(0,255,145,.6)", 1);
|
||||
line(0, -86, 0, -19, "rgba(0,255,145,.6)", 1);
|
||||
line(0, 19, 0, 86, "rgba(0,255,145,.6)", 1);
|
||||
line(-60, -6, -60, 6, "rgba(0,255,145,.45)", 0.75);
|
||||
line(60, -6, 60, 6, "rgba(0,255,145,.45)", 0.75);
|
||||
line(-6, -60, 6, -60, "rgba(0,255,145,.45)", 0.75);
|
||||
line(-6, 60, 6, 60, "rgba(0,255,145,.45)", 0.75);
|
||||
line(-38, -3.5, -38, 3.5, "rgba(0,255,145,.3)", 0.5);
|
||||
line(38, -3.5, 38, 3.5, "rgba(0,255,145,.3)", 0.5);
|
||||
line(-3.5, -38, 3.5, -38, "rgba(0,255,145,.3)", 0.5);
|
||||
line(-3.5, 38, 3.5, 38, "rgba(0,255,145,.3)", 0.5);
|
||||
path([[-74, -58], [-74, -74], [-58, -74]], "rgba(0,255,145,.75)", 1.5);
|
||||
path([[58, -74], [74, -74], [74, -58]], "rgba(0,255,145,.75)", 1.5);
|
||||
path([[-74, 58], [-74, 74], [-58, 74]], "rgba(0,255,145,.75)", 1.5);
|
||||
path([[58, 74], [74, 74], [74, 58]], "rgba(0,255,145,.75)", 1.5);
|
||||
circle(6, "rgba(0,255,145,.7)", 1);
|
||||
circle(82, .2, 1, [4, 10]);
|
||||
circle(60, .15, 0.75, [2, 16]);
|
||||
circle(16, .3, 0.75);
|
||||
line(-86, 0, -19, 0, .6, 1);
|
||||
line(19, 0, 86, 0, .6, 1);
|
||||
line(0, -86, 0, -19, .6, 1);
|
||||
line(0, 19, 0, 86, .6, 1);
|
||||
line(-60, -6, -60, 6, .45, 0.75);
|
||||
line(60, -6, 60, 6, .45, 0.75);
|
||||
line(-6, -60, 6, -60, .45, 0.75);
|
||||
line(-6, 60, 6, 60, .45, 0.75);
|
||||
line(-38, -3.5, -38, 3.5, .3, 0.5);
|
||||
line(38, -3.5, 38, 3.5, .3, 0.5);
|
||||
line(-3.5, -38, 3.5, -38, .3, 0.5);
|
||||
line(-3.5, 38, 3.5, 38, .3, 0.5);
|
||||
path([[-74, -58], [-74, -74], [-58, -74]], .75, 1.5);
|
||||
path([[58, -74], [74, -74], [74, -58]], .75, 1.5);
|
||||
path([[-74, 58], [-74, 74], [-58, 74]], .75, 1.5);
|
||||
path([[58, 74], [74, 74], [74, 58]], .75, 1.5);
|
||||
circle(6, .7, 1);
|
||||
|
||||
context.save();
|
||||
context.shadowColor = "rgba(0,0,0,.85)";
|
||||
context.shadowBlur = 3;
|
||||
context.beginPath();
|
||||
context.arc(cx, cy, 2.5 * unit, 0, Math.PI * 2);
|
||||
context.fillStyle = "rgba(0,255,145,.9)";
|
||||
context.fillStyle = hudRgba(.9);
|
||||
context.fill();
|
||||
context.shadowBlur = 0;
|
||||
context.beginPath();
|
||||
context.arc(cx, cy, 1 * unit, 0, Math.PI * 2);
|
||||
context.fillStyle = "rgba(255,255,255,.7)";
|
||||
@@ -1271,17 +1305,9 @@ function drawCrosshairOverlayToCanvas(context, canvasWidth, canvasHeight, size)
|
||||
function drawVignetteAndScanlines(context, canvasWidth, canvasHeight) {
|
||||
context.save();
|
||||
for (var y = 0; y < canvasHeight; y += 4) {
|
||||
context.fillStyle = "rgba(0,255,145,.012)";
|
||||
context.fillStyle = hudRgba(.012);
|
||||
context.fillRect(0, y, canvasWidth, 1);
|
||||
}
|
||||
var vignette = context.createRadialGradient(
|
||||
canvasWidth * 0.5, canvasHeight * 0.5, canvasWidth * 0.25,
|
||||
canvasWidth * 0.5, canvasHeight * 0.5, canvasWidth * 0.75
|
||||
);
|
||||
vignette.addColorStop(0, "rgba(0,0,0,0)");
|
||||
vignette.addColorStop(1, "rgba(0,0,0,.58)");
|
||||
context.fillStyle = vignette;
|
||||
context.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||
context.restore();
|
||||
}
|
||||
|
||||
@@ -1339,7 +1365,7 @@ function drawHudOverlayToCanvas(context, canvasWidth, canvasHeight) {
|
||||
context.fillText(document.getElementById("cam-live-text").textContent, canvasWidth / 2 + (6 * camScale * scaleToCanvas), padding);
|
||||
context.restore();
|
||||
|
||||
drawCrosshairOverlayToCanvas(context, canvasWidth, canvasHeight, 270 * camScale * scaleToCanvas);
|
||||
drawCrosshairOverlayToCanvas(context, canvasWidth, canvasHeight, 405 * camScale * scaleToCanvas);
|
||||
drawVignetteAndScanlines(context, canvasWidth, canvasHeight);
|
||||
}
|
||||
|
||||
@@ -1544,7 +1570,12 @@ function toggleStatPanel() {
|
||||
setStatPanelCollapsed(!panel.classList.contains("collapsed"));
|
||||
}
|
||||
|
||||
window.addEventListener("storage", function (e) {
|
||||
if (e.key === "hudHexColor" && e.newValue) applyHudColor(e.newValue);
|
||||
});
|
||||
|
||||
window.addEventListener("load", function () {
|
||||
try { var h = localStorage.getItem("hudHexColor"); if (h) applyHudColor(h); } catch (e) {}
|
||||
setText("cam-host", hostUrl);
|
||||
updateModeDisplay();
|
||||
updateMotorDisplay();
|
||||
|
||||
Reference in New Issue
Block a user