Files
qt5-legatus-legacy/Lts/Tools/Trajectories/HTML-TrajectoryViewer/trajectoryViewer.html
T
2026-08-13 18:33:10 +02:00

153 lines
4.7 KiB
HTML
Executable File

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>3D Kurven - Dynamisches Fenster</title>
<!-- <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js"></script> -->
<script src="lib/plotly-3.3.0.min.js" charset="utf-8"></script>
<script src="lib/papaparse.min.js" charset="utf-8"></script>
<style>
body { margin: 0; font-family: 'Segoe UI', sans-serif; display: flex; flex-direction: column; height: 100vh; background: #111; color: white; }
.header {
padding: 15px;
background: #222;
display: flex;
align-items: center;
gap: 20px;
border-bottom: 1px solid #444;
flex-wrap: wrap;
}
#chart { flex-grow: 1; width: 100%; }
.controls { display: flex; align-items: center; gap: 10px; }
input[type="number"] {
width: 60px;
padding: 5px;
border-radius: 4px;
border: 1px solid #555;
background: #333;
color: white;
}
input[type="file"] { color: #aaa; }
button {
padding: 5px 15px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover { background: #0056b3; }
.hint { font-size: 0.75em; color: #888; }
</style>
</head>
<body>
<div class="header">
<strong>3D Trajektorien</strong>
<input type="file" id="csv-file" accept=".csv">
<div class="controls">
<label for="point-count">Punkte:</label>
<input type="number" id="point-count" value="20" min="0">
<button id="update-btn">Anwenden</button>
</div>
<span class="hint">(0 = alle Punkte)</span>
</div>
<div id="chart"></div>
<script>
const chartDiv = document.getElementById('chart');
const pointInput = document.getElementById('point-count');
const updateBtn = document.getElementById('update-btn');
let rawCSVData = null; // Speicher für die geladenen Daten
// 1. Datei einlesen
document.getElementById('csv-file').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
Papa.parse(file, {
header: true,
skipEmptyLines: true,
dynamicTyping: true,
complete: function(results) {
rawCSVData = results.data;
renderData();
}
});
});
// 2. Button-Event für die Aktualisierung
updateBtn.addEventListener('click', renderData);
// Enter-Taste im Eingabefeld abfangen
pointInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') renderData();
});
function renderData() {
if (!rawCSVData) return;
const windowSize = parseInt(pointInput.value) || 0;
const curves = {};
// Daten nach ID gruppieren
rawCSVData.forEach(row => {
if (row.id === undefined || row.id === null) return;
if (!curves[row.id]) {
curves[row.id] = { x: [], y: [], z: [] };
}
curves[row.id].x.push(row.x);
curves[row.id].y.push(row.y);
curves[row.id].z.push(row.z);
});
const traces = Object.keys(curves).map(id => {
let x = curves[id].x;
let y = curves[id].y;
let z = curves[id].z;
// Fenster anwenden, wenn windowSize > 0
if (windowSize > 0) {
x = x.slice(-windowSize);
y = y.slice(-windowSize);
z = z.slice(-windowSize);
}
return {
x: x,
y: y,
z: z,
mode: 'lines+markers',
type: 'scatter3d',
name: `ID ${id}`,
line: { width: 4 },
marker: {
size: 3,
// Verlaufseffekt: Die neuesten Punkte sind am kräftigsten
opacity: x.map((_, i) => (i + 1) / x.length)
}
};
});
const layout = {
paper_bgcolor: '#111',
font: { color: '#ccc' },
scene: {
aspectmode: 'data',
xaxis: { gridcolor: '#333' },
yaxis: { gridcolor: '#333' },
zaxis: { gridcolor: '#333' }
},
margin: { l: 0, r: 0, b: 0, t: 0 },
showlegend: true,
legend: { x: 0, y: 1 }
};
Plotly.newPlot(chartDiv, traces, layout, { responsive: true, displaylogo: false });
}
</script>
</body>
</html>