From 527e28736af8211cb383121c48aca816bb61cb3f Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Mon, 5 Jan 2026 13:43:09 -0600 Subject: [PATCH] Make traffic graph scale symmetric to keep zero line in middle --- assets/js/app.js | 109 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 33 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 761cedb2..2c7bd6d8 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -100,46 +100,89 @@ const SensorChart = { } } - // Y-axis configuration - const yAxisConfig = autoScale ? { - beginAtZero: showZeroLine, - ticks: { - callback: function(value) { - if (unit === 'bps') { - return formatBps(value) + // For traffic graphs, calculate symmetric scale to keep zero in the middle + let yAxisConfig = {} + if (autoScale) { + if (showZeroLine && unit === 'bps') { + // Find max absolute value to make symmetric scale + let maxAbsValue = 0 + datasets.forEach(dataset => { + dataset.data.forEach(point => { + maxAbsValue = Math.max(maxAbsValue, Math.abs(point.y)) + }) + }) + // Add 10% padding + maxAbsValue = maxAbsValue * 1.1 + + yAxisConfig = { + min: -maxAbsValue, + max: maxAbsValue, + ticks: { + callback: function(value) { + return formatBps(value) + } + }, + grid: { + color: function(context) { + // Make the zero line more prominent + if (context.tick.value === 0) { + return 'rgba(0, 0, 0, 0.3)' + } + return 'rgba(0, 0, 0, 0.05)' + }, + lineWidth: function(context) { + // Make the zero line thicker + if (context.tick.value === 0) { + return 2 + } + return 1 + } } - return value + unit } - }, - grid: { - color: function(context) { - // Make the zero line more prominent - if (showZeroLine && context.tick.value === 0) { - return 'rgba(0, 0, 0, 0.3)' + } else { + yAxisConfig = { + beginAtZero: showZeroLine, + ticks: { + callback: function(value) { + if (unit === 'bps') { + return formatBps(value) + } + return value + unit + } + }, + grid: { + color: function(context) { + // Make the zero line more prominent + if (showZeroLine && context.tick.value === 0) { + return 'rgba(0, 0, 0, 0.3)' + } + return 'rgba(0, 0, 0, 0.05)' + }, + lineWidth: function(context) { + // Make the zero line thicker + if (showZeroLine && context.tick.value === 0) { + return 2 + } + return 1 + } } - return 'rgba(0, 0, 0, 0.05)' - }, - lineWidth: function(context) { - // Make the zero line thicker - if (showZeroLine && context.tick.value === 0) { - return 2 - } - return 1 } } - } : { - min: 0, - max: 100, - ticks: { - callback: function(value) { - if (unit === 'bps') { - return formatBps(value) + } else { + yAxisConfig = { + min: 0, + max: 100, + ticks: { + callback: function(value) { + if (unit === 'bps') { + return formatBps(value) + } + return value + unit } - return value + unit + }, + grid: { + color: 'rgba(0, 0, 0, 0.05)' } - }, - grid: { - color: 'rgba(0, 0, 0, 0.05)' } }