153 lines
4.7 KiB
HTML
Executable File
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> |