feat: Implement intelligent decimation for Chart.js plots and optimize zoom handling in historical session component

This commit is contained in:
Miguel 2025-08-16 17:03:25 +02:00
parent fe1df15942
commit 5cd3d61128
2 changed files with 53 additions and 11 deletions

View File

@ -291,6 +291,25 @@ const ChartjsHistoricalPlot = ({
currentTimeRange
});
// Calculate intelligent decimation based on canvas width
const canvasWidth = canvasRef.current?.clientWidth || 800; // Default fallback
const maxPointsPerDataset = data.datasets.reduce((max, dataset) =>
Math.max(max, dataset.data.length), 0);
// Decimation should activate when we have more than 2x points than pixels
const pixelRatio = 2; // 2 points per pixel
const decimationThreshold = canvasWidth * pixelRatio;
const shouldDecimate = maxPointsPerDataset > decimationThreshold;
const samples = Math.max(Math.floor(canvasWidth * 0.8), 200); // 80% of canvas width, min 200
console.log('📊 Decimation analysis:', {
canvasWidth,
maxPointsPerDataset,
decimationThreshold,
shouldDecimate,
samples
});
const config = {
type: 'line',
data: data,
@ -305,12 +324,12 @@ const ChartjsHistoricalPlot = ({
mode: 'index'
},
plugins: {
// Configure decimation for better performance with large datasets
// Configure intelligent decimation based on pixel density
decimation: {
enabled: true,
enabled: shouldDecimate,
algorithm: 'min-max',
samples: 500,
threshold: 1000 // Enable decimation when more than 1000 points
samples: samples,
threshold: decimationThreshold
},
title: {
display: !!plotConfig.name,
@ -517,11 +536,21 @@ const ChartjsHistoricalPlot = ({
<Text fontSize="sm" color={textColor}>
{dataPointsCount.toLocaleString()} data points
{dataPointsCount > 1000 && (
<Text as="span" ml={2} fontSize="xs" color="blue.500">
(Min/Max decimation active)
</Text>
)}
{(() => {
const canvasWidth = canvasRef.current?.clientWidth || 800;
const maxPoints = dataPointsCount;
const decimationThreshold = canvasWidth * 2;
const shouldDecimate = maxPoints > decimationThreshold;
if (shouldDecimate) {
return (
<Text as="span" ml={2} fontSize="xs" color="blue.500">
(Min/Max decimation: {canvasWidth} px ÷ {maxPoints} pts)
</Text>
);
}
return null;
})()}
{dataPointsCount === 0 && chartRef.current && (
<Text as="span" ml={2} fontSize="xs" color="orange.500">
No data in current view - use pan/zoom to navigate

View File

@ -371,8 +371,21 @@ export default function PlotHistoricalSession({
console.log('📊 Zoom: New central time:', newCentralTime, 'Range seconds:', newRangeSeconds)
// Use debounced update to sync all components
debouncedTimeChange(newCentralTime, newRangeSeconds)
// Para zoom-in (agrandar), solo actualizar el rango de visualización
// No recargar datos ya que tenemos suficientes datos en memoria
const currentRangeSeconds = timeRangeSeconds
const rangeRatio = newRangeSeconds / currentRangeSeconds
if (rangeRatio < 1.0) { // Zoom-in (agrandar imagen)
console.log('📊 Zoom-in detected: Updating display range without reloading data')
// Solo actualizar el estado local para el rango de visualización
setCentralTime(newCentralTime)
setTimeRangeSeconds(newRangeSeconds)
// NO llamar debouncedTimeChange para evitar recarga de datos
} else { // Zoom-out, usar lógica normal
console.log('📊 Zoom-out detected: Using debounced update')
debouncedTimeChange(newCentralTime, newRangeSeconds)
}
}
const handlePanToTimeRange = (start, end) => {