diff --git a/assets/js/graph.js b/assets/js/graph.js index 123952a..cb59959 100644 --- a/assets/js/graph.js +++ b/assets/js/graph.js @@ -3,7 +3,7 @@ import uPlot from 'uplot' import { RelativeScale } from './scale' import { formatNumber, formatTimestampSeconds } from './util' -import { uPlotTooltipPlugin } from './tooltip' +import { uPlotTooltipPlugin, uPlotIsZoomedPlugin } from './plugins' import { FAVORITE_SERVERS_STORAGE_KEY } from './favorites' @@ -18,6 +18,7 @@ export class GraphDisplayManager { this._hasLoadedSettings = false this._initEventListenersOnce = false this._showOnlyFavorites = false + this._isPlotZoomed = false } addGraphPoint (timestamp, playerCounts) { @@ -49,8 +50,14 @@ export class GraphDisplayManager { } } - // Paint updated data structure - this._plotInstance.setData(this.getGraphData()) + // If not zoomed, paint updated data structure + // Otherwise flag the plot data as dirty with repainting to be handled by #handlePlotZoomOut + // This prevents #addGraphPoint calls from resetting the graph's zoom state + if (!this._isPlotZoomed) { + this._plotInstance.setData(this.getGraphData()) + } else { + this._isPlotZoomedDataDirty = true + } } loadLocalStorage () { @@ -244,7 +251,8 @@ export class GraphDisplayManager { } else { this._app.tooltip.hide() } - }) + }), + uPlotIsZoomedPlugin(this.handlePlotZoomIn, this.handlePlotZoomOut) ], ...this.getPlotSize(), cursor: { @@ -339,6 +347,21 @@ export class GraphDisplayManager { this._resizeRequestTimeout = undefined } + handlePlotZoomIn = () => { + this._isPlotZoomed = true + } + + handlePlotZoomOut = () => { + this._isPlotZoomed = false + + // Test if the data has changed while the plot was zoomed in + if (this._isPlotZoomedDataDirty) { + this._isPlotZoomedDataDirty = false + + this._plotInstance.setData(this.getGraphData()) + } + } + initEventListeners () { if (!this._initEventListenersOnce) { this._initEventListenersOnce = true @@ -446,6 +469,9 @@ export class GraphDisplayManager { this._graphData = [] this._hasLoadedSettings = false + this._isPlotZoomed = false + this._isPlotZoomedDataDirty = false + // Fire #clearTimeout if the timeout is currently defined if (this._resizeRequestTimeout) { clearTimeout(this._resizeRequestTimeout) diff --git a/assets/js/plugins.js b/assets/js/plugins.js index 0595d7d..1027d61 100644 --- a/assets/js/plugins.js +++ b/assets/js/plugins.js @@ -26,3 +26,27 @@ export function uPlotTooltipPlugin (onHover) { } } } + +export function uPlotIsZoomedPlugin (onZoomIn, onZoomOut) { + return { + hooks: { + setSelect: u => { + u._zoomPluginIgnoreNextSetScale = true + + if (onZoomIn) { + onZoomIn(u) + } + }, + setScale: u => { + if (typeof u._zoomPluginIgnoreNextSetScale !== 'boolean') { + return + } + if (u._zoomPluginIgnoreNextSetScale) { + u._zoomPluginIgnoreNextSetScale = false + } else if (onZoomOut) { + onZoomOut(u) + } + } + } + } +} diff --git a/assets/js/servers.js b/assets/js/servers.js index f103f67..717e0ac 100644 --- a/assets/js/servers.js +++ b/assets/js/servers.js @@ -3,7 +3,7 @@ import uPlot from 'uplot' import { RelativeScale } from './scale' import { formatNumber, formatTimestampSeconds, formatDate, formatMinecraftServerAddress, formatMinecraftVersions } from './util' -import { uPlotTooltipPlugin } from './tooltip' +import { uPlotTooltipPlugin } from './plugins' import MISSING_FAVICON from '../images/missing_favicon.svg'