stream-charts 1.2.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +809 -1022
- package/changes.md +36 -0
- package/dist/app/charts/Chart.d.ts +35 -139
- package/dist/app/charts/Chart.d.ts.map +1 -0
- package/dist/app/charts/Chart.js +74 -65
- package/dist/app/charts/Chart.js.map +1 -1
- package/dist/app/charts/axes/AxesState.d.ts +26 -18
- package/dist/app/charts/axes/AxesState.d.ts.map +1 -0
- package/dist/app/charts/axes/AxesState.js +26 -24
- package/dist/app/charts/axes/AxesState.js.map +1 -1
- package/dist/app/charts/axes/AxisInterval.d.ts +44 -26
- package/dist/app/charts/axes/AxisInterval.d.ts.map +1 -0
- package/dist/app/charts/axes/AxisInterval.js +48 -29
- package/dist/app/charts/axes/AxisInterval.js.map +1 -1
- package/dist/app/charts/axes/BaseAxisRange.d.ts +46 -22
- package/dist/app/charts/axes/BaseAxisRange.d.ts.map +1 -0
- package/dist/app/charts/axes/BaseAxisRange.js +17 -12
- package/dist/app/charts/axes/BaseAxisRange.js.map +1 -1
- package/dist/app/charts/axes/ContinuousAxis.d.ts +47 -6
- package/dist/app/charts/axes/ContinuousAxis.d.ts.map +1 -0
- package/dist/app/charts/axes/ContinuousAxis.js +160 -27
- package/dist/app/charts/axes/ContinuousAxis.js.map +1 -1
- package/dist/app/charts/axes/ContinuousAxisRange.d.ts +29 -10
- package/dist/app/charts/axes/ContinuousAxisRange.d.ts.map +1 -0
- package/dist/app/charts/axes/ContinuousAxisRange.js +29 -11
- package/dist/app/charts/axes/ContinuousAxisRange.js.map +1 -1
- package/dist/app/charts/axes/EmptyAxis.d.ts +5 -2
- package/dist/app/charts/axes/EmptyAxis.d.ts.map +1 -0
- package/dist/app/charts/axes/EmptyAxis.js +30 -9
- package/dist/app/charts/axes/EmptyAxis.js.map +1 -1
- package/dist/app/charts/axes/OrdinalAxis.d.ts +5 -3
- package/dist/app/charts/axes/OrdinalAxis.d.ts.map +1 -0
- package/dist/app/charts/axes/OrdinalAxis.js +39 -16
- package/dist/app/charts/axes/OrdinalAxis.js.map +1 -1
- package/dist/app/charts/axes/OrdinalAxisRange.d.ts +76 -13
- package/dist/app/charts/axes/OrdinalAxisRange.d.ts.map +1 -0
- package/dist/app/charts/axes/OrdinalAxisRange.js +95 -16
- package/dist/app/charts/axes/OrdinalAxisRange.js.map +1 -1
- package/dist/app/charts/axes/autoScale.d.ts +111 -0
- package/dist/app/charts/axes/autoScale.d.ts.map +1 -0
- package/dist/app/charts/axes/autoScale.js +188 -0
- package/dist/app/charts/axes/autoScale.js.map +1 -0
- package/dist/app/charts/axes/axes.d.ts +273 -150
- package/dist/app/charts/axes/axes.d.ts.map +1 -0
- package/dist/app/charts/axes/axes.js +808 -583
- package/dist/app/charts/axes/axes.js.map +1 -1
- package/dist/app/charts/d3types.d.ts +40 -11
- package/dist/app/charts/d3types.d.ts.map +1 -0
- package/dist/app/charts/d3types.js +3 -0
- package/dist/app/charts/d3types.js.map +1 -1
- package/dist/app/charts/datasources/StreamingDataSource.d.ts +149 -0
- package/dist/app/charts/datasources/StreamingDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/StreamingDataSource.js +110 -0
- package/dist/app/charts/datasources/StreamingDataSource.js.map +1 -0
- package/dist/app/charts/datasources/iteratesDataSource.d.ts +73 -0
- package/dist/app/charts/datasources/iteratesDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/iteratesDataSource.js +87 -0
- package/dist/app/charts/datasources/iteratesDataSource.js.map +1 -0
- package/dist/app/charts/datasources/ordinalDataSource.d.ts +75 -0
- package/dist/app/charts/datasources/ordinalDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/ordinalDataSource.js +135 -0
- package/dist/app/charts/datasources/ordinalDataSource.js.map +1 -0
- package/dist/app/charts/datasources/outlierDataSource.d.ts +53 -0
- package/dist/app/charts/datasources/outlierDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/outlierDataSource.js +57 -0
- package/dist/app/charts/datasources/outlierDataSource.js.map +1 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.d.ts +77 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.js +85 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.js.map +1 -0
- package/dist/app/charts/filters/regexFilter.d.ts +31 -4
- package/dist/app/charts/filters/regexFilter.d.ts.map +1 -0
- package/dist/app/charts/filters/regexFilter.js +38 -4
- package/dist/app/charts/filters/regexFilter.js.map +1 -1
- package/dist/app/charts/hooks/AxesProvider.d.ts +21 -0
- package/dist/app/charts/hooks/AxesProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/AxesProvider.js +213 -0
- package/dist/app/charts/hooks/AxesProvider.js.map +1 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.d.ts +25 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.js +76 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.js.map +1 -0
- package/dist/app/charts/hooks/ChartProvider.d.ts +40 -0
- package/dist/app/charts/hooks/ChartProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/ChartProvider.js +33 -0
- package/dist/app/charts/hooks/ChartProvider.js.map +1 -0
- package/dist/app/charts/hooks/InteractionProvider.d.ts +23 -0
- package/dist/app/charts/hooks/InteractionProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/InteractionProvider.js +60 -0
- package/dist/app/charts/hooks/InteractionProvider.js.map +1 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.d.ts +16 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.js +76 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.js.map +1 -0
- package/dist/app/charts/hooks/defaultAxesValues.d.ts +11 -0
- package/dist/app/charts/hooks/defaultAxesValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultAxesValues.js +36 -0
- package/dist/app/charts/hooks/defaultAxesValues.js.map +1 -0
- package/dist/app/charts/hooks/defaultMouseValues.d.ts +9 -0
- package/dist/app/charts/hooks/defaultMouseValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultMouseValues.js +23 -0
- package/dist/app/charts/hooks/defaultMouseValues.js.map +1 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.d.ts +13 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.js +23 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.js.map +1 -0
- package/dist/app/charts/hooks/defaultTooltipValues.d.ts +9 -0
- package/dist/app/charts/hooks/defaultTooltipValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultTooltipValues.js +21 -0
- package/dist/app/charts/hooks/defaultTooltipValues.js.map +1 -0
- package/dist/app/charts/hooks/defaultUseChartValues.d.ts +14 -0
- package/dist/app/charts/hooks/defaultUseChartValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultUseChartValues.js +30 -0
- package/dist/app/charts/hooks/defaultUseChartValues.js.map +1 -0
- package/dist/app/charts/hooks/useAxes.d.ts +49 -36
- package/dist/app/charts/hooks/useAxes.d.ts.map +1 -0
- package/dist/app/charts/hooks/useAxes.js +16 -176
- package/dist/app/charts/hooks/useAxes.js.map +1 -1
- package/dist/app/charts/hooks/useCanvasSurface.d.ts +25 -0
- package/dist/app/charts/hooks/useCanvasSurface.d.ts.map +1 -0
- package/dist/app/charts/hooks/useCanvasSurface.js +18 -0
- package/dist/app/charts/hooks/useCanvasSurface.js.map +1 -0
- package/dist/app/charts/hooks/useChart.d.ts +30 -44
- package/dist/app/charts/hooks/useChart.d.ts.map +1 -0
- package/dist/app/charts/hooks/useChart.js +26 -48
- package/dist/app/charts/hooks/useChart.js.map +1 -1
- package/dist/app/charts/hooks/useDataSource.d.ts +68 -0
- package/dist/app/charts/hooks/useDataSource.d.ts.map +1 -0
- package/dist/app/charts/hooks/useDataSource.js +63 -0
- package/dist/app/charts/hooks/useDataSource.js.map +1 -0
- package/dist/app/charts/hooks/useHoveredSeries.d.ts +25 -0
- package/dist/app/charts/hooks/useHoveredSeries.d.ts.map +1 -0
- package/dist/app/charts/hooks/useHoveredSeries.js +15 -0
- package/dist/app/charts/hooks/useHoveredSeries.js.map +1 -0
- package/dist/app/charts/hooks/useMouse.d.ts +46 -22
- package/dist/app/charts/hooks/useMouse.d.ts.map +1 -0
- package/dist/app/charts/hooks/useMouse.js +12 -56
- package/dist/app/charts/hooks/useMouse.js.map +1 -1
- package/dist/app/charts/hooks/usePlotDimensions.d.ts +25 -13
- package/dist/app/charts/hooks/usePlotDimensions.d.ts.map +1 -0
- package/dist/app/charts/hooks/usePlotDimensions.js +6 -62
- package/dist/app/charts/hooks/usePlotDimensions.js.map +1 -1
- package/dist/app/charts/hooks/useTooltip.d.ts +24 -26
- package/dist/app/charts/hooks/useTooltip.d.ts.map +1 -0
- package/dist/app/charts/hooks/useTooltip.js +12 -42
- package/dist/app/charts/hooks/useTooltip.js.map +1 -1
- package/dist/app/charts/index.d.ts +66 -0
- package/dist/app/charts/index.d.ts.map +1 -0
- package/dist/app/charts/index.js +87 -0
- package/dist/app/charts/index.js.map +1 -0
- package/dist/app/charts/legends/Legend.d.ts +33 -12
- package/dist/app/charts/legends/Legend.d.ts.map +1 -0
- package/dist/app/charts/legends/Legend.js +138 -379
- package/dist/app/charts/legends/Legend.js.map +1 -1
- package/dist/app/charts/legends/constants.d.ts +19 -0
- package/dist/app/charts/legends/constants.d.ts.map +1 -0
- package/dist/app/charts/legends/constants.js +34 -0
- package/dist/app/charts/legends/constants.js.map +1 -0
- package/dist/app/charts/observables/ChartData.d.ts +1 -0
- package/dist/app/charts/observables/ChartData.d.ts.map +1 -0
- package/dist/app/charts/observables/iterates.d.ts +13 -7
- package/dist/app/charts/observables/iterates.d.ts.map +1 -0
- package/dist/app/charts/observables/iterates.js +42 -9
- package/dist/app/charts/observables/iterates.js.map +1 -1
- package/dist/app/charts/observables/ordinals.d.ts +70 -12
- package/dist/app/charts/observables/ordinals.d.ts.map +1 -0
- package/dist/app/charts/observables/ordinals.js +127 -48
- package/dist/app/charts/observables/ordinals.js.map +1 -1
- package/dist/app/charts/observables/outliers.d.ts +18 -0
- package/dist/app/charts/observables/outliers.d.ts.map +1 -0
- package/dist/app/charts/observables/outliers.js +2 -0
- package/dist/app/charts/observables/outliers.js.map +1 -0
- package/dist/app/charts/plots/BarPlot.d.ts +87 -13
- package/dist/app/charts/plots/BarPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/BarPlot.js +603 -356
- package/dist/app/charts/plots/BarPlot.js.map +1 -1
- package/dist/app/charts/plots/OutlierPlot.d.ts +123 -0
- package/dist/app/charts/plots/OutlierPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/OutlierPlot.js +430 -0
- package/dist/app/charts/plots/OutlierPlot.js.map +1 -0
- package/dist/app/charts/plots/PoincarePlot.d.ts +92 -14
- package/dist/app/charts/plots/PoincarePlot.d.ts.map +1 -0
- package/dist/app/charts/plots/PoincarePlot.js +523 -364
- package/dist/app/charts/plots/PoincarePlot.js.map +1 -1
- package/dist/app/charts/plots/RasterPlot.d.ts +31 -10
- package/dist/app/charts/plots/RasterPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/RasterPlot.js +198 -306
- package/dist/app/charts/plots/RasterPlot.js.map +1 -1
- package/dist/app/charts/plots/ScatterPlot.d.ts +77 -21
- package/dist/app/charts/plots/ScatterPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/ScatterPlot.js +359 -302
- package/dist/app/charts/plots/ScatterPlot.js.map +1 -1
- package/dist/app/charts/plots/autoScaleYAxes.d.ts +43 -0
- package/dist/app/charts/plots/autoScaleYAxes.d.ts.map +1 -0
- package/dist/app/charts/plots/autoScaleYAxes.js +71 -0
- package/dist/app/charts/plots/autoScaleYAxes.js.map +1 -0
- package/dist/app/charts/plots/colorizedLine.d.ts +61 -0
- package/dist/app/charts/plots/colorizedLine.d.ts.map +1 -0
- package/dist/app/charts/plots/colorizedLine.js +157 -0
- package/dist/app/charts/plots/colorizedLine.js.map +1 -0
- package/dist/app/charts/plots/constants.d.ts +7 -0
- package/dist/app/charts/plots/constants.d.ts.map +1 -0
- package/dist/app/charts/plots/constants.js +11 -0
- package/dist/app/charts/plots/constants.js.map +1 -0
- package/dist/app/charts/plots/hitTesting.d.ts +88 -0
- package/dist/app/charts/plots/hitTesting.d.ts.map +1 -0
- package/dist/app/charts/plots/hitTesting.js +136 -0
- package/dist/app/charts/plots/hitTesting.js.map +1 -0
- package/dist/app/charts/plots/plot.d.ts +52 -16
- package/dist/app/charts/plots/plot.d.ts.map +1 -0
- package/dist/app/charts/plots/plot.js +108 -35
- package/dist/app/charts/plots/plot.js.map +1 -1
- package/dist/app/charts/plots/useCanvasZoomPan.d.ts +119 -0
- package/dist/app/charts/plots/useCanvasZoomPan.d.ts.map +1 -0
- package/dist/app/charts/plots/useCanvasZoomPan.js +113 -0
- package/dist/app/charts/plots/useCanvasZoomPan.js.map +1 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.d.ts +103 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.d.ts.map +1 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.js +257 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.js.map +1 -0
- package/dist/app/charts/series/baseSeries.d.ts +60 -8
- package/dist/app/charts/series/baseSeries.d.ts.map +1 -0
- package/dist/app/charts/series/baseSeries.js +53 -8
- package/dist/app/charts/series/baseSeries.js.map +1 -1
- package/dist/app/charts/series/iterateSeries.d.ts +9 -8
- package/dist/app/charts/series/iterateSeries.d.ts.map +1 -0
- package/dist/app/charts/series/iterateSeries.js +7 -7
- package/dist/app/charts/series/iterateSeries.js.map +1 -1
- package/dist/app/charts/series/ordinalSeries.d.ts +27 -13
- package/dist/app/charts/series/ordinalSeries.d.ts.map +1 -0
- package/dist/app/charts/series/ordinalSeries.js +29 -15
- package/dist/app/charts/series/ordinalSeries.js.map +1 -1
- package/dist/app/charts/series/outlierSeries.d.ts +142 -0
- package/dist/app/charts/series/outlierSeries.d.ts.map +1 -0
- package/dist/app/charts/series/outlierSeries.js +82 -0
- package/dist/app/charts/series/outlierSeries.js.map +1 -0
- package/dist/app/charts/series/timeSeries.d.ts +13 -9
- package/dist/app/charts/series/timeSeries.d.ts.map +1 -0
- package/dist/app/charts/series/timeSeries.js +6 -3
- package/dist/app/charts/series/timeSeries.js.map +1 -1
- package/dist/app/charts/series/timeSeriesChartData.d.ts +18 -10
- package/dist/app/charts/series/timeSeriesChartData.d.ts.map +1 -0
- package/dist/app/charts/series/timeSeriesChartData.js +28 -14
- package/dist/app/charts/series/timeSeriesChartData.js.map +1 -1
- package/dist/app/charts/styling/barPlotStyle.d.ts +46 -2
- package/dist/app/charts/styling/barPlotStyle.d.ts.map +1 -0
- package/dist/app/charts/styling/barPlotStyle.js +37 -3
- package/dist/app/charts/styling/barPlotStyle.js.map +1 -1
- package/dist/app/charts/styling/canvasStyle.d.ts +53 -0
- package/dist/app/charts/styling/canvasStyle.d.ts.map +1 -0
- package/dist/app/charts/styling/canvasStyle.js +71 -0
- package/dist/app/charts/styling/canvasStyle.js.map +1 -0
- package/dist/app/charts/styling/margins.d.ts +21 -2
- package/dist/app/charts/styling/margins.d.ts.map +1 -0
- package/dist/app/charts/styling/margins.js +25 -4
- package/dist/app/charts/styling/margins.js.map +1 -1
- package/dist/app/charts/styling/svgStyle.d.ts +10 -56
- package/dist/app/charts/styling/svgStyle.d.ts.map +1 -0
- package/dist/app/charts/styling/svgStyle.js +3 -78
- package/dist/app/charts/styling/svgStyle.js.map +1 -1
- package/dist/app/charts/subscriptions/viewDrivers.d.ts +124 -0
- package/dist/app/charts/subscriptions/viewDrivers.d.ts.map +1 -0
- package/dist/app/charts/subscriptions/viewDrivers.js +338 -0
- package/dist/app/charts/subscriptions/viewDrivers.js.map +1 -0
- package/dist/app/charts/tooltips/BarPlotTooltipContent.d.ts +12 -78
- package/dist/app/charts/tooltips/BarPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/BarPlotTooltipContent.js +65 -257
- package/dist/app/charts/tooltips/BarPlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.d.ts +9 -0
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.js +16 -0
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.js.map +1 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.d.ts +30 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.js +26 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.js.map +1 -0
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.d.ts +22 -72
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.js +104 -171
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.d.ts +32 -8
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.js +62 -115
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.d.ts +39 -12
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.js +162 -134
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/Tooltip.d.ts +27 -32
- package/dist/app/charts/tooltips/Tooltip.d.ts.map +1 -0
- package/dist/app/charts/tooltips/Tooltip.js +37 -81
- package/dist/app/charts/tooltips/Tooltip.js.map +1 -1
- package/dist/app/charts/tooltips/TooltipContent.d.ts +81 -0
- package/dist/app/charts/tooltips/TooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/TooltipContent.js +99 -0
- package/dist/app/charts/tooltips/TooltipContent.js.map +1 -0
- package/dist/app/charts/tooltips/tooltipUtils.d.ts +186 -36
- package/dist/app/charts/tooltips/tooltipUtils.d.ts.map +1 -0
- package/dist/app/charts/tooltips/tooltipUtils.js +277 -48
- package/dist/app/charts/tooltips/tooltipUtils.js.map +1 -1
- package/dist/app/charts/tooltips/useOutlierTooltip.d.ts +59 -0
- package/dist/app/charts/tooltips/useOutlierTooltip.d.ts.map +1 -0
- package/dist/app/charts/tooltips/useOutlierTooltip.js +16 -0
- package/dist/app/charts/tooltips/useOutlierTooltip.js.map +1 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.d.ts +51 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.d.ts.map +1 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.js +52 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.js.map +1 -0
- package/dist/app/charts/tooltips/useTooltipStyle.d.ts +11 -0
- package/dist/app/charts/tooltips/useTooltipStyle.d.ts.map +1 -0
- package/dist/app/charts/tooltips/useTooltipStyle.js +14 -0
- package/dist/app/charts/tooltips/useTooltipStyle.js.map +1 -0
- package/dist/app/charts/trackers/Tracker.d.ts +22 -6
- package/dist/app/charts/trackers/Tracker.d.ts.map +1 -0
- package/dist/app/charts/trackers/Tracker.js +36 -22
- package/dist/app/charts/trackers/Tracker.js.map +1 -1
- package/dist/app/charts/trackers/trackerUtils.d.ts +40 -18
- package/dist/app/charts/trackers/trackerUtils.d.ts.map +1 -0
- package/dist/app/charts/trackers/trackerUtils.js +213 -300
- package/dist/app/charts/trackers/trackerUtils.js.map +1 -1
- package/dist/app/charts/utils.d.ts +72 -33
- package/dist/app/charts/utils.d.ts.map +1 -0
- package/dist/app/charts/utils.js +87 -42
- package/dist/app/charts/utils.js.map +1 -1
- package/dist/index.d.ts +2 -45
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -72
- package/dist/index.js.map +1 -1
- package/package.json +87 -46
- package/src/app/charts/Chart.tsx +132 -168
- package/src/app/charts/axes/AxesState.ts +27 -29
- package/src/app/charts/axes/AxisInterval.ts +57 -32
- package/src/app/charts/axes/BaseAxisRange.ts +47 -27
- package/src/app/charts/axes/ContinuousAxis.tsx +235 -39
- package/src/app/charts/axes/ContinuousAxisRange.ts +29 -11
- package/src/app/charts/axes/EmptyAxis.tsx +52 -17
- package/src/app/charts/axes/OrdinalAxis.tsx +54 -28
- package/src/app/charts/axes/OrdinalAxisRange.ts +96 -16
- package/src/app/charts/axes/autoScale.ts +244 -0
- package/src/app/charts/axes/axes.ts +954 -735
- package/src/app/charts/d3types.ts +42 -13
- package/src/app/charts/datasources/StreamingDataSource.ts +214 -0
- package/src/app/charts/datasources/iteratesDataSource.ts +122 -0
- package/src/app/charts/datasources/ordinalDataSource.ts +205 -0
- package/src/app/charts/datasources/outlierDataSource.ts +90 -0
- package/src/app/charts/datasources/timeSeriesDataSource.ts +133 -0
- package/src/app/charts/filters/regexFilter.ts +45 -5
- package/src/app/charts/hooks/AxesProvider.tsx +301 -0
- package/src/app/charts/hooks/CanvasSurfaceProvider.tsx +117 -0
- package/src/app/charts/hooks/ChartProvider.tsx +79 -0
- package/src/app/charts/hooks/InteractionProvider.tsx +88 -0
- package/src/app/charts/hooks/PlotDimensionsProvider.tsx +109 -0
- package/src/app/charts/hooks/defaultAxesValues.ts +40 -0
- package/src/app/charts/hooks/defaultMouseValues.ts +24 -0
- package/src/app/charts/hooks/defaultPlotDimensions.ts +27 -0
- package/src/app/charts/hooks/defaultTooltipValues.tsx +23 -0
- package/src/app/charts/hooks/defaultUseChartValues.tsx +36 -0
- package/src/app/charts/hooks/useAxes.tsx +60 -228
- package/src/app/charts/hooks/useCanvasSurface.tsx +35 -0
- package/src/app/charts/hooks/useChart.tsx +47 -106
- package/src/app/charts/hooks/useDataSource.tsx +106 -0
- package/src/app/charts/hooks/useHoveredSeries.tsx +33 -0
- package/src/app/charts/hooks/useMouse.tsx +58 -82
- package/src/app/charts/hooks/usePlotDimensions.tsx +25 -89
- package/src/app/charts/hooks/useTooltip.tsx +32 -63
- package/src/app/charts/index.ts +213 -0
- package/src/app/charts/legends/Legend.tsx +198 -479
- package/src/app/charts/legends/constants.ts +37 -0
- package/src/app/charts/observables/iterates.ts +32 -12
- package/src/app/charts/observables/ordinals.ts +141 -67
- package/src/app/charts/observables/outliers.ts +20 -0
- package/src/app/charts/plots/BarPlot.tsx +784 -666
- package/src/app/charts/plots/OutlierPlot.tsx +685 -0
- package/src/app/charts/plots/PoincarePlot.tsx +707 -489
- package/src/app/charts/plots/RasterPlot.tsx +253 -445
- package/src/app/charts/plots/ScatterPlot.tsx +480 -463
- package/src/app/charts/plots/autoScaleYAxes.ts +102 -0
- package/src/app/charts/plots/colorizedLine.ts +185 -0
- package/src/app/charts/plots/constants.ts +16 -0
- package/src/app/charts/plots/hitTesting.ts +198 -0
- package/src/app/charts/plots/plot.ts +138 -44
- package/src/app/charts/plots/useCanvasZoomPan.ts +240 -0
- package/src/app/charts/plots/useStreamingTimeAxes.ts +384 -0
- package/src/app/charts/series/baseSeries.ts +81 -14
- package/src/app/charts/series/iterateSeries.ts +8 -8
- package/src/app/charts/series/ordinalSeries.ts +35 -20
- package/src/app/charts/series/outlierSeries.ts +188 -0
- package/src/app/charts/series/timeSeries.ts +14 -12
- package/src/app/charts/series/timeSeriesChartData.ts +31 -17
- package/src/app/charts/styling/barPlotStyle.ts +48 -5
- package/src/app/charts/styling/canvasStyle.ts +86 -0
- package/src/app/charts/styling/margins.ts +28 -4
- package/src/app/charts/styling/svgStyle.ts +10 -91
- package/src/app/charts/subscriptions/viewDrivers.ts +447 -0
- package/src/app/charts/tooltips/BarPlotTooltipContent.tsx +156 -380
- package/src/app/charts/tooltips/DefaultOutlierTooltipContent.tsx +40 -0
- package/src/app/charts/tooltips/OutlierPlotTooltipContent.tsx +67 -0
- package/src/app/charts/tooltips/PoincarePlotTooltipContent.tsx +229 -292
- package/src/app/charts/tooltips/RasterPlotTooltipContent.tsx +164 -217
- package/src/app/charts/tooltips/ScatterPlotTooltipContent.tsx +373 -236
- package/src/app/charts/tooltips/Tooltip.tsx +58 -124
- package/src/app/charts/tooltips/TooltipContent.tsx +177 -0
- package/src/app/charts/tooltips/tooltipUtils.ts +359 -61
- package/src/app/charts/tooltips/useOutlierTooltip.tsx +68 -0
- package/src/app/charts/tooltips/useTooltipPlacement.ts +86 -0
- package/src/app/charts/tooltips/useTooltipStyle.ts +15 -0
- package/src/app/charts/trackers/Tracker.tsx +68 -33
- package/src/app/charts/trackers/trackerUtils.ts +263 -376
- package/src/app/charts/utils.ts +90 -48
- package/src/index.ts +2 -322
- package/dist/app/charts/axes/AxesState.test.d.ts +0 -1
- package/dist/app/charts/axes/AxesState.test.js +0 -30
- package/dist/app/charts/axes/AxesState.test.js.map +0 -1
- package/dist/app/charts/axes/AxisInterval.test.d.ts +0 -1
- package/dist/app/charts/axes/AxisInterval.test.js +0 -120
- package/dist/app/charts/axes/AxisInterval.test.js.map +0 -1
- package/dist/app/charts/axes/ContinuousAxisRange.test.d.ts +0 -1
- package/dist/app/charts/axes/ContinuousAxisRange.test.js +0 -47
- package/dist/app/charts/axes/ContinuousAxisRange.test.js.map +0 -1
- package/dist/app/charts/axes/OrdinalAxisRange.test.d.ts +0 -1
- package/dist/app/charts/axes/OrdinalAxisRange.test.js +0 -48
- package/dist/app/charts/axes/OrdinalAxisRange.test.js.map +0 -1
- package/dist/app/charts/filters/regexFilter.test.d.ts +0 -1
- package/dist/app/charts/filters/regexFilter.test.js +0 -11
- package/dist/app/charts/filters/regexFilter.test.js.map +0 -1
- package/dist/app/charts/hooks/useDataObservable.d.ts +0 -72
- package/dist/app/charts/hooks/useDataObservable.js +0 -74
- package/dist/app/charts/hooks/useDataObservable.js.map +0 -1
- package/dist/app/charts/hooks/useInitialData.d.ts +0 -36
- package/dist/app/charts/hooks/useInitialData.js +0 -28
- package/dist/app/charts/hooks/useInitialData.js.map +0 -1
- package/dist/app/charts/observables/iterates.test.d.ts +0 -1
- package/dist/app/charts/observables/iterates.test.js +0 -180
- package/dist/app/charts/observables/iterates.test.js.map +0 -1
- package/dist/app/charts/observables/ordinals.test.d.ts +0 -1
- package/dist/app/charts/observables/ordinals.test.js +0 -102
- package/dist/app/charts/observables/ordinals.test.js.map +0 -1
- package/dist/app/charts/series/datumSeries.test.d.ts +0 -1
- package/dist/app/charts/series/datumSeries.test.js +0 -50
- package/dist/app/charts/series/datumSeries.test.js.map +0 -1
- package/dist/app/charts/styling/margins.test.d.ts +0 -1
- package/dist/app/charts/styling/margins.test.js +0 -19
- package/dist/app/charts/styling/margins.test.js.map +0 -1
- package/dist/app/charts/subscriptions/subscription.test.d.ts +0 -1
- package/dist/app/charts/subscriptions/subscription.test.js +0 -395
- package/dist/app/charts/subscriptions/subscription.test.js.map +0 -1
- package/dist/app/charts/subscriptions/subscriptions.d.ts +0 -100
- package/dist/app/charts/subscriptions/subscriptions.js +0 -449
- package/dist/app/charts/subscriptions/subscriptions.js.map +0 -1
- package/src/app/charts/axes/AxesState.test.ts +0 -34
- package/src/app/charts/axes/AxisInterval.test.ts +0 -143
- package/src/app/charts/axes/ContinuousAxisRange.test.ts +0 -55
- package/src/app/charts/axes/OrdinalAxisRange.test.ts +0 -55
- package/src/app/charts/filters/regexFilter.test.ts +0 -13
- package/src/app/charts/hooks/useDataObservable.tsx +0 -170
- package/src/app/charts/hooks/useInitialData.tsx +0 -64
- package/src/app/charts/observables/iterates.test.ts +0 -201
- package/src/app/charts/observables/ordinals.test.ts +0 -135
- package/src/app/charts/series/datumSeries.test.ts +0 -60
- package/src/app/charts/styling/margins.test.ts +0 -22
- package/src/app/charts/subscriptions/subscription.test.ts +0 -499
- package/src/app/charts/subscriptions/subscriptions.ts +0 -635
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { ContinuousAxisRange } from "./ContinuousAxisRange";
|
|
2
2
|
import * as d3 from "d3";
|
|
3
|
-
import {
|
|
3
|
+
import { clipToArea } from "../plots/plot";
|
|
4
|
+
import { fontStringFor } from "../utils";
|
|
4
5
|
import { OrdinalAxisRange } from "./OrdinalAxisRange";
|
|
5
6
|
import { AxisInterval } from "./AxisInterval";
|
|
7
|
+
/** Default tick length, in pixels, matching d3-axis's default `tickSize`. */
|
|
8
|
+
const TICK_SIZE = 6;
|
|
9
|
+
/** Default gap between the end of a tick and its label, matching d3-axis's default `tickPadding`. */
|
|
10
|
+
const TICK_PADDING = 3;
|
|
6
11
|
/**
|
|
7
12
|
* Factory function to create a default AxisTickStyle with the default font,
|
|
8
|
-
* no rotation, and no
|
|
13
|
+
* no rotation, and no autorotation.
|
|
14
|
+
* @return The default axis tick style
|
|
9
15
|
*/
|
|
10
16
|
export function defaultAxisTickStyle() {
|
|
11
17
|
return {
|
|
@@ -17,6 +23,7 @@ export function defaultAxisTickStyle() {
|
|
|
17
23
|
/**
|
|
18
24
|
* Factory function to create a default AxesFont with the default font size, color,
|
|
19
25
|
* family, and weight.
|
|
26
|
+
* @return The default axes font
|
|
20
27
|
*/
|
|
21
28
|
export function defaultAxesFont() {
|
|
22
29
|
return {
|
|
@@ -29,6 +36,7 @@ export function defaultAxesFont() {
|
|
|
29
36
|
/**
|
|
30
37
|
* Factory function to create a default SeriesLineStyle with the default color, line width,
|
|
31
38
|
* highlight color, and highlight width.
|
|
39
|
+
* @return The default series line style
|
|
32
40
|
*/
|
|
33
41
|
export function defaultLineStyle() {
|
|
34
42
|
return {
|
|
@@ -39,296 +47,348 @@ export function defaultLineStyle() {
|
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
/**
|
|
42
|
-
*
|
|
50
|
+
* The concrete kind of an axis, set by every axis-creator function to its own unique value.
|
|
51
|
+
* Lets code that only has a `BaseAxis` (e.g. a plot's `axesFor` validating an `axisAssignments`
|
|
52
|
+
* entry) discriminate the concrete axis shape at runtime -- `BaseAxis`/`ContinuousNumericAxis`/
|
|
53
|
+
* `OrdinalStringAxis` are plain structural interfaces, so a type-level cast (`as ContinuousNumericAxis`)
|
|
54
|
+
* cannot do that; this field is what actually can.
|
|
55
|
+
* Note: replaces enums to support `erasableSyntaxOnly`
|
|
56
|
+
* TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
|
|
43
57
|
*/
|
|
44
|
-
export
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
AxisLocation[AxisLocation["Bottom"] = 2] = "Bottom";
|
|
51
|
-
AxisLocation[AxisLocation["Top"] = 3] = "Top";
|
|
52
|
-
})(AxisLocation || (AxisLocation = {}));
|
|
53
|
-
/*
|
|
54
|
-
axis clip path definition
|
|
58
|
+
export const AxisType = {
|
|
59
|
+
ContinuousNumeric: "ContinuousNumeric",
|
|
60
|
+
OrdinalString: "OrdinalString",
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The axis component that creates each type of axis (with its article), for messages about axes
|
|
55
64
|
*/
|
|
65
|
+
const AXIS_COMPONENTS = {
|
|
66
|
+
[AxisType.ContinuousNumeric]: "a <ContinuousAxis> (or an <EmptyAxis>)",
|
|
67
|
+
[AxisType.OrdinalString]: "an <OrdinalAxis>",
|
|
68
|
+
};
|
|
56
69
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* @param
|
|
61
|
-
* @param
|
|
62
|
-
* @param
|
|
63
|
-
* @
|
|
64
|
-
* @param plotDimensions The dimensions of the plot
|
|
65
|
-
* @param margin The margins around the plot
|
|
66
|
-
* @return The ID of the clip-path
|
|
70
|
+
* Checks that a plot's axis is of the type the plot needs (e.g. a bar plot needs an ordinal x-axis).
|
|
71
|
+
* A missing axis passes, since the plots already skip the series whose axes aren't found.
|
|
72
|
+
* @param plotName The name of the plot's component (e.g. "RasterPlot")
|
|
73
|
+
* @param dimension Whether the axis is the plot's x-axis or its y-axis
|
|
74
|
+
* @param axis The axis (`undefined` when it isn't found)
|
|
75
|
+
* @param expected The axis type the plot needs
|
|
76
|
+
* @throws Error when the axis isn't of the expected type, naming the axis component it needs to be
|
|
67
77
|
*/
|
|
68
|
-
export function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
plotDimensions.width;
|
|
74
|
-
const height = location === AxisLocation.Top ? margin.top + 1 :
|
|
75
|
-
location === AxisLocation.Bottom ? margin.bottom - 1 :
|
|
76
|
-
plotDimensions.height;
|
|
77
|
-
// remove the old clipping region and add a new one with the updated plot dimensions
|
|
78
|
-
svg.select(`#${clipPathId}-defs`).remove();
|
|
79
|
-
svg
|
|
80
|
-
.append('defs')
|
|
81
|
-
.attr('id', `${clipPathId}-defs`)
|
|
82
|
-
.append("clipPath")
|
|
83
|
-
.attr("id", clipPathId)
|
|
84
|
-
.append("rect")
|
|
85
|
-
.attr("x", 0)
|
|
86
|
-
.attr("y", location === AxisLocation.Bottom ? -1 : -margin.top)
|
|
87
|
-
.attr("width", width)
|
|
88
|
-
.attr("height", height);
|
|
89
|
-
return clipPathId;
|
|
78
|
+
export function checkAxisType(plotName, dimension, axis, expected) {
|
|
79
|
+
if (axis !== undefined && axis.axisType !== expected) {
|
|
80
|
+
throw Error(`<${plotName}> needs its ${dimension}-axis to be ${AXIS_COMPONENTS[expected]}, but the ` +
|
|
81
|
+
`${dimension}-axis "${axis.axisId}" is ${AXIS_COMPONENTS[axis.axisType]}`);
|
|
82
|
+
}
|
|
90
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* The possible locations of an axis.
|
|
86
|
+
* Note: replaces enums to support `erasableSyntaxOnly`
|
|
87
|
+
* TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
|
|
88
|
+
*/
|
|
89
|
+
export const AxisLocation = {
|
|
90
|
+
// y-axes
|
|
91
|
+
Left: "Left",
|
|
92
|
+
Right: "Right",
|
|
93
|
+
// x-axes
|
|
94
|
+
Bottom: "Bottom",
|
|
95
|
+
Top: "Top"
|
|
96
|
+
};
|
|
91
97
|
/*
|
|
92
|
-
category axes
|
|
98
|
+
category (ordinal) axes
|
|
93
99
|
*/
|
|
94
100
|
/**
|
|
95
|
-
* Adds a category axis to the specified location
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* @param
|
|
101
|
+
* Adds a category axis to the specified location, registering its draw function with the canvas
|
|
102
|
+
* context. When the location is top or bottom, the category axis represents the x-axis; when the
|
|
103
|
+
* location is left or right, it represents the y-axis.
|
|
104
|
+
* @param cc The canvas context to register the axis' draw function with
|
|
99
105
|
* @param axisId A unique ID for the axis
|
|
100
|
-
* @param svg The SVG selection (d3)
|
|
101
106
|
* @param location The location of the axis
|
|
102
|
-
* @param categories
|
|
107
|
+
* @param categories The category names (the axis' `update` function can replace them later)
|
|
103
108
|
* @param axisLabel The axis label
|
|
104
109
|
* @param axesLabelFont The font for the axis label
|
|
105
|
-
* @param axisTickStyle Styling information for the ticks (
|
|
110
|
+
* @param axisTickStyle Styling information for the ticks (font, rotation, etc.)
|
|
106
111
|
* @param plotDimensions The dimensions of the plot
|
|
107
112
|
* @param margin The plot margin
|
|
108
|
-
* @param setAxisRangeFor
|
|
109
|
-
* @param setOriginalAxisRangeFor
|
|
110
|
-
* @return
|
|
113
|
+
* @param setAxisRangeFor Callback that sets the axis range for the specified axis
|
|
114
|
+
* @param setOriginalAxisRangeFor Callback that sets the original axis range for the specified axis
|
|
115
|
+
* @return An {@link OrdinalStringAxis}
|
|
111
116
|
*/
|
|
112
|
-
export function addOrdinalStringAxis(
|
|
117
|
+
export function addOrdinalStringAxis(cc, axisId, location, categories, axisLabel, axesLabelFont, axisTickStyle, plotDimensions, margin, setAxisRangeFor, setOriginalAxisRangeFor) {
|
|
113
118
|
switch (location) {
|
|
114
119
|
case AxisLocation.Top:
|
|
115
120
|
case AxisLocation.Bottom:
|
|
116
|
-
return addOrdinalStringXAxis(
|
|
121
|
+
return addOrdinalStringXAxis(cc, axisId, location, categories, axisLabel, axesLabelFont, axisTickStyle, plotDimensions, margin, setAxisRangeFor, setOriginalAxisRangeFor);
|
|
117
122
|
case AxisLocation.Left:
|
|
118
123
|
case AxisLocation.Right:
|
|
119
|
-
return addOrdinalStringYAxis(
|
|
124
|
+
return addOrdinalStringYAxis(cc, axisId, location, categories, axisLabel, axesLabelFont, axisTickStyle, plotDimensions, margin, setAxisRangeFor, setOriginalAxisRangeFor);
|
|
120
125
|
}
|
|
121
126
|
}
|
|
122
127
|
/**
|
|
123
|
-
* Adds a category axis
|
|
124
|
-
* @
|
|
128
|
+
* Adds a category x-axis (top or bottom), registering its draw function with the canvas context.
|
|
129
|
+
* See {@link addOrdinalStringAxis}.
|
|
130
|
+
*
|
|
131
|
+
* NOTE ON FIDELITY: the original SVG version rotated tick labels using each label's own
|
|
132
|
+
* `getBBox()` to compute a per-label rotation origin, which let long labels pivot around their own
|
|
133
|
+
* visual center/corner. Canvas `measureText` has no bbox-offset equivalent, so this version rotates
|
|
134
|
+
* every label about its anchor point at the tick instead. At `rotation: 0` (the common case) this
|
|
135
|
+
* produces the same centered layout as before; at non-zero rotations the labels will be close but
|
|
136
|
+
* not pixel-identical to the old SVG output -- worth a visual check if you use tick rotation.
|
|
137
|
+
* @param cc The canvas context to register the axis' draw function with
|
|
125
138
|
* @param axisId A unique ID for the axis
|
|
126
|
-
* @param
|
|
127
|
-
* @param
|
|
128
|
-
* @param categories An array holding the category names
|
|
139
|
+
* @param location The location of the axis (top or bottom)
|
|
140
|
+
* @param categories The category names (the axis' `update` function can replace them later)
|
|
129
141
|
* @param axisLabel The axis label
|
|
130
|
-
* @param axesLabelFont The font for the axis label
|
|
131
|
-
*
|
|
142
|
+
* @param axesLabelFont The font for the axis label (its color is also the color of the axis line,
|
|
143
|
+
* ticks, and tick labels)
|
|
144
|
+
* @param axisTickStyle Styling information for the ticks (font, rotation, etc.)
|
|
132
145
|
* @param plotDimensions The dimensions of the plot
|
|
133
146
|
* @param margin The plot margin
|
|
134
|
-
* @param setAxisRangeFor
|
|
135
|
-
* @param setOriginalAxisRangeFor
|
|
136
|
-
* @return
|
|
147
|
+
* @param setAxisRangeFor Callback that sets the axis range for the specified axis
|
|
148
|
+
* @param setOriginalAxisRangeFor Callback that sets the original axis range for the specified axis
|
|
149
|
+
* @return An {@link OrdinalStringAxis}
|
|
137
150
|
*/
|
|
138
|
-
function addOrdinalStringXAxis(
|
|
139
|
-
const scale = d3.scaleBand()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
.
|
|
151
|
-
.
|
|
152
|
-
.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
.
|
|
158
|
-
.
|
|
159
|
-
.
|
|
160
|
-
|
|
151
|
+
function addOrdinalStringXAxis(cc, axisId, location, categories, axisLabel, axesLabelFont, axisTickStyle, plotDimensions, margin, setAxisRangeFor, setOriginalAxisRangeFor) {
|
|
152
|
+
const scale = d3.scaleBand().domain(categories).range([0, plotDimensions.width]);
|
|
153
|
+
let currentDimensions = plotDimensions;
|
|
154
|
+
let currentMargin = margin;
|
|
155
|
+
let currentFont = axesLabelFont;
|
|
156
|
+
const currentTickStyle = axisTickStyle;
|
|
157
|
+
let highlighted = false;
|
|
158
|
+
let highlightColor = defaultLineStyle().highlightColor;
|
|
159
|
+
let highlightLineWidth = defaultLineStyle().highlightWidth;
|
|
160
|
+
const drawHandle = `x-axis-ordinal-${cc.chartId}-${axisId}`;
|
|
161
|
+
const draw = (context) => {
|
|
162
|
+
const { context2D } = context;
|
|
163
|
+
context2D.save();
|
|
164
|
+
context2D.translate(currentMargin.left, yTranslation(location, currentDimensions, currentMargin));
|
|
165
|
+
context2D.save();
|
|
166
|
+
clipToArea(context, { width: currentDimensions.width, height: currentMargin.bottom }, { x: 0, y: location === AxisLocation.Bottom ? -1 : -currentMargin.top });
|
|
167
|
+
const axisColor = highlighted ? highlightColor : currentFont.color;
|
|
168
|
+
context2D.strokeStyle = axisColor;
|
|
169
|
+
context2D.fillStyle = axisColor;
|
|
170
|
+
context2D.lineWidth = highlighted ? highlightLineWidth : 1;
|
|
171
|
+
context2D.font = fontStringFor(currentTickStyle.font.size, currentTickStyle.font.family, currentTickStyle.font.weight);
|
|
172
|
+
context2D.textBaseline = 'middle';
|
|
173
|
+
// domain line
|
|
174
|
+
context2D.beginPath();
|
|
175
|
+
context2D.moveTo(0, 0);
|
|
176
|
+
context2D.lineTo(currentDimensions.width, 0);
|
|
177
|
+
context2D.stroke();
|
|
178
|
+
const tickDirection = location === AxisLocation.Bottom ? 1 : -1;
|
|
179
|
+
const degrees = location === AxisLocation.Bottom ? -currentTickStyle.rotation : currentTickStyle.rotation;
|
|
161
180
|
const radians = degrees * Math.PI / 180;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
.
|
|
179
|
-
.
|
|
180
|
-
.
|
|
181
|
-
|
|
182
|
-
.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
181
|
+
categories.forEach(category => {
|
|
182
|
+
var _a;
|
|
183
|
+
const x = ((_a = scale(category)) !== null && _a !== void 0 ? _a : 0) + scale.bandwidth() / 2;
|
|
184
|
+
context2D.beginPath();
|
|
185
|
+
context2D.moveTo(x, 0);
|
|
186
|
+
context2D.lineTo(x, TICK_SIZE * tickDirection);
|
|
187
|
+
context2D.stroke();
|
|
188
|
+
context2D.save();
|
|
189
|
+
context2D.translate(x, (TICK_SIZE + TICK_PADDING) * tickDirection);
|
|
190
|
+
context2D.rotate(radians);
|
|
191
|
+
context2D.textAlign = radians === 0 ? 'center' : 'end';
|
|
192
|
+
context2D.fillText(category, 0, 0);
|
|
193
|
+
context2D.restore();
|
|
194
|
+
});
|
|
195
|
+
context2D.restore(); // pop the clip
|
|
196
|
+
// axis label (absolute position, not clipped, matches the old behavior)
|
|
197
|
+
context2D.fillStyle = axisColor;
|
|
198
|
+
context2D.font = fontStringFor(currentFont.size, currentFont.family, currentFont.weight);
|
|
199
|
+
context2D.textAlign = 'center';
|
|
200
|
+
// (a bottom label sits on the canvas' bottom edge, so it's drawn above it, descenders and all)
|
|
201
|
+
context2D.textBaseline = location === AxisLocation.Top ? 'hanging' : 'bottom';
|
|
202
|
+
const labelX = ordinalLabelXTranslation(location, currentDimensions, currentMargin, currentFont) - currentMargin.left;
|
|
203
|
+
const labelY = ordinalLabelYTranslation(location, currentDimensions, currentMargin) - yTranslation(location, currentDimensions, currentMargin);
|
|
204
|
+
context2D.fillText(axisLabel, labelX, labelY);
|
|
205
|
+
context2D.restore();
|
|
206
|
+
};
|
|
207
|
+
cc.register(drawHandle, draw, 0);
|
|
208
|
+
const categorySize = () => scale.bandwidth();
|
|
209
|
+
return {
|
|
210
|
+
axisId,
|
|
211
|
+
location,
|
|
212
|
+
axisType: AxisType.OrdinalString,
|
|
213
|
+
scale,
|
|
214
|
+
categorySize: categorySize(),
|
|
215
|
+
update: (updatedCategories, range, originalRange, plotDimensions, margin) => {
|
|
216
|
+
// reassign the closed-over `categories` (not just a local variable) so `draw`'s own
|
|
217
|
+
// `categories.forEach(...)` picks up the change on the next redraw too
|
|
218
|
+
categories = updatedCategories;
|
|
219
|
+
const updatedRange = AxisInterval.from(Math.min(range.start, 0), Math.max(range.end, plotDimensions.width));
|
|
220
|
+
scale.domain(categories).range(updatedRange.asTuple());
|
|
221
|
+
currentDimensions = plotDimensions;
|
|
222
|
+
currentMargin = margin;
|
|
186
223
|
setAxisRangeFor(axisId, range);
|
|
187
224
|
setOriginalAxisRangeFor(axisId, originalRange);
|
|
188
|
-
|
|
189
|
-
|
|
225
|
+
cc.requestRedraw();
|
|
226
|
+
return categorySize();
|
|
227
|
+
},
|
|
228
|
+
setHighlighted: (isHighlighted, color, lineWidth) => {
|
|
229
|
+
highlighted = isHighlighted;
|
|
230
|
+
if (color !== undefined)
|
|
231
|
+
highlightColor = color;
|
|
232
|
+
if (lineWidth !== undefined)
|
|
233
|
+
highlightLineWidth = lineWidth;
|
|
234
|
+
cc.requestRedraw();
|
|
235
|
+
},
|
|
236
|
+
updateFont: (font) => {
|
|
237
|
+
// the font's color is used for the label, the axis line, the ticks, and the tick
|
|
238
|
+
// labels; the tick labels' size, family, and weight stay at axisTickStyle.font's
|
|
239
|
+
currentFont = font;
|
|
240
|
+
cc.requestRedraw();
|
|
241
|
+
}
|
|
242
|
+
};
|
|
190
243
|
}
|
|
191
244
|
/**
|
|
192
|
-
* Adds a category axis
|
|
193
|
-
* @
|
|
245
|
+
* Adds a category y-axis (left or right), registering its draw function with the canvas context.
|
|
246
|
+
* See {@link addOrdinalStringAxis}.
|
|
247
|
+
* @param cc The canvas context to register the axis' draw function with
|
|
194
248
|
* @param axisId A unique ID for the axis
|
|
195
|
-
* @param
|
|
196
|
-
* @param
|
|
197
|
-
* @param categories An array holding the category names
|
|
249
|
+
* @param location The location of the axis (left or right)
|
|
250
|
+
* @param categories The category names (the axis' `update` function can replace them later)
|
|
198
251
|
* @param axisLabel The axis label
|
|
199
|
-
* @param axesLabelFont The font for the axis label
|
|
200
|
-
*
|
|
252
|
+
* @param axesLabelFont The font for the axis label (its color is also the color of the axis line,
|
|
253
|
+
* ticks, and tick labels)
|
|
254
|
+
* @param axisTickStyle Styling information for the ticks (font, rotation, etc.)
|
|
201
255
|
* @param plotDimensions The dimensions of the plot
|
|
202
256
|
* @param margin The plot margin
|
|
203
|
-
* @param setAxisRangeFor
|
|
204
|
-
* @param setOriginalAxisRangeFor
|
|
205
|
-
* @return
|
|
257
|
+
* @param setAxisRangeFor Callback that sets the axis range for the specified axis
|
|
258
|
+
* @param setOriginalAxisRangeFor Callback that sets the original axis range for the specified axis
|
|
259
|
+
* @return An {@link OrdinalStringAxis}
|
|
206
260
|
*/
|
|
207
|
-
function addOrdinalStringYAxis(
|
|
208
|
-
const scale = d3.scaleBand()
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
.
|
|
236
|
-
|
|
237
|
-
.
|
|
238
|
-
.
|
|
239
|
-
.
|
|
240
|
-
.
|
|
241
|
-
.
|
|
242
|
-
|
|
243
|
-
.
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
261
|
+
function addOrdinalStringYAxis(cc, axisId, location, categories, axisLabel, axesLabelFont, axisTickStyle, plotDimensions, margin, setAxisRangeFor, setOriginalAxisRangeFor) {
|
|
262
|
+
const scale = d3.scaleBand().domain(categories).range([0, plotDimensions.height]);
|
|
263
|
+
let currentDimensions = plotDimensions;
|
|
264
|
+
let currentMargin = margin;
|
|
265
|
+
let currentFont = axesLabelFont;
|
|
266
|
+
const currentTickStyle = axisTickStyle;
|
|
267
|
+
let highlighted = false;
|
|
268
|
+
let highlightColor = defaultLineStyle().highlightColor;
|
|
269
|
+
let highlightLineWidth = defaultLineStyle().highlightWidth;
|
|
270
|
+
const drawHandle = `y-axis-ordinal-${cc.chartId}-${axisId}`;
|
|
271
|
+
const draw = (context) => {
|
|
272
|
+
const { context2D } = context;
|
|
273
|
+
context2D.save();
|
|
274
|
+
context2D.translate(xTranslation(location, currentDimensions, currentMargin), currentMargin.top);
|
|
275
|
+
context2D.save();
|
|
276
|
+
const clipWidth = location === AxisLocation.Left ? currentMargin.left : currentMargin.right;
|
|
277
|
+
// the boundary that abuts the domain line (x=0) is nudged 1px past it (into the plot side),
|
|
278
|
+
// so the line's 1px-wide stroke -- centered on x=0, spanning -0.5 to +0.5 -- isn't clipped
|
|
279
|
+
// in half; mirrors the same -1 fudge used for the bottom x-axis's domain line
|
|
280
|
+
clipToArea(context, { width: clipWidth, height: currentDimensions.height }, { x: location === AxisLocation.Left ? -clipWidth + 1 : -1, y: 0 });
|
|
281
|
+
const axisColor = highlighted ? highlightColor : currentFont.color;
|
|
282
|
+
context2D.strokeStyle = axisColor;
|
|
283
|
+
context2D.fillStyle = axisColor;
|
|
284
|
+
context2D.lineWidth = highlighted ? highlightLineWidth : 1;
|
|
285
|
+
context2D.font = fontStringFor(currentTickStyle.font.size, currentTickStyle.font.family, currentTickStyle.font.weight);
|
|
286
|
+
// matches the old SVG version, which forced text-anchor "end" for ordinal ticks
|
|
287
|
+
// regardless of Left/Right location
|
|
288
|
+
context2D.textAlign = 'end';
|
|
289
|
+
context2D.textBaseline = 'middle';
|
|
290
|
+
// domain line
|
|
291
|
+
context2D.beginPath();
|
|
292
|
+
context2D.moveTo(0, 0);
|
|
293
|
+
context2D.lineTo(0, currentDimensions.height);
|
|
294
|
+
context2D.stroke();
|
|
295
|
+
const degrees = location === AxisLocation.Left ? -currentTickStyle.rotation : currentTickStyle.rotation;
|
|
296
|
+
const radians = degrees * Math.PI / 180;
|
|
297
|
+
const tickDirection = location === AxisLocation.Left ? -1 : 1;
|
|
298
|
+
// offset the label past the tick mark plus a little padding, rather than flush against
|
|
299
|
+
// the axis line -- this was previously just `0` (Left) / `scale.bandwidth()` (Right),
|
|
300
|
+
// which put the label's text-anchor edge right on top of the axis line with no gap
|
|
301
|
+
const xTick = (TICK_SIZE + TICK_PADDING) * tickDirection;
|
|
302
|
+
categories.forEach(category => {
|
|
303
|
+
var _a;
|
|
304
|
+
const y = ((_a = scale(category)) !== null && _a !== void 0 ? _a : 0) + scale.bandwidth() / 2;
|
|
305
|
+
context2D.beginPath();
|
|
306
|
+
context2D.moveTo(0, y);
|
|
307
|
+
context2D.lineTo(TICK_SIZE * tickDirection, y);
|
|
308
|
+
context2D.stroke();
|
|
309
|
+
context2D.save();
|
|
310
|
+
context2D.translate(xTick, y);
|
|
311
|
+
context2D.rotate(radians);
|
|
312
|
+
context2D.fillText(category, 0, 0);
|
|
313
|
+
context2D.restore();
|
|
314
|
+
});
|
|
315
|
+
context2D.restore(); // pop the clip
|
|
316
|
+
// axis label, rotated -90deg, matching the old SVG version
|
|
317
|
+
context2D.save();
|
|
318
|
+
const labelX = ordinalLabelXTranslation(location, currentDimensions, currentMargin, currentFont) - xTranslation(location, currentDimensions, currentMargin);
|
|
319
|
+
const labelY = ordinalLabelYTranslation(location, currentDimensions, currentMargin) - currentMargin.top;
|
|
320
|
+
context2D.translate(labelX, labelY);
|
|
321
|
+
context2D.rotate(-Math.PI / 2);
|
|
322
|
+
context2D.fillStyle = axisColor;
|
|
323
|
+
context2D.font = fontStringFor(currentFont.size, currentFont.family, currentFont.weight);
|
|
324
|
+
context2D.textAlign = 'center';
|
|
325
|
+
context2D.textBaseline = 'alphabetic';
|
|
326
|
+
context2D.fillText(axisLabel, 0, 0);
|
|
327
|
+
context2D.restore();
|
|
328
|
+
context2D.restore();
|
|
329
|
+
};
|
|
330
|
+
cc.register(drawHandle, draw, 0);
|
|
331
|
+
const categorySize = () => scale.bandwidth();
|
|
332
|
+
return {
|
|
333
|
+
axisId,
|
|
334
|
+
location,
|
|
335
|
+
axisType: AxisType.OrdinalString,
|
|
336
|
+
scale,
|
|
337
|
+
categorySize: categorySize(),
|
|
338
|
+
update: (updatedCategories, range, originalRange, plotDimensions, margin) => {
|
|
339
|
+
// reassign the closed-over `categories` (not just a local variable) so `draw`'s own
|
|
340
|
+
// `categories.forEach(...)` picks up the change on the next redraw too
|
|
341
|
+
categories = updatedCategories;
|
|
342
|
+
const updatedRange = AxisInterval.from(Math.min(range.start, 0), Math.max(range.end, plotDimensions.height));
|
|
343
|
+
scale.domain(categories).range(updatedRange.asTuple());
|
|
344
|
+
currentDimensions = plotDimensions;
|
|
345
|
+
currentMargin = margin;
|
|
247
346
|
setAxisRangeFor(axisId, range);
|
|
248
347
|
setOriginalAxisRangeFor(axisId, originalRange);
|
|
249
|
-
|
|
250
|
-
|
|
348
|
+
cc.requestRedraw();
|
|
349
|
+
return categorySize();
|
|
350
|
+
},
|
|
351
|
+
setHighlighted: (isHighlighted, color, lineWidth) => {
|
|
352
|
+
highlighted = isHighlighted;
|
|
353
|
+
if (color !== undefined)
|
|
354
|
+
highlightColor = color;
|
|
355
|
+
if (lineWidth !== undefined)
|
|
356
|
+
highlightLineWidth = lineWidth;
|
|
357
|
+
cc.requestRedraw();
|
|
358
|
+
},
|
|
359
|
+
updateFont: (font) => {
|
|
360
|
+
// the font's color is used for the label, the axis line, the ticks, and the tick
|
|
361
|
+
// labels; the tick labels' size, family, and weight stay at axisTickStyle.font's
|
|
362
|
+
currentFont = font;
|
|
363
|
+
cc.requestRedraw();
|
|
364
|
+
}
|
|
365
|
+
};
|
|
251
366
|
}
|
|
252
367
|
/**
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
* @param
|
|
256
|
-
* @param axis The category axis to be updated
|
|
257
|
-
* @param svg The SVG selection (d3)
|
|
258
|
-
* @param location The location of the axis
|
|
259
|
-
* @param names An array holding the category names
|
|
260
|
-
* @param axesLabelFont The font for the axis label
|
|
261
|
-
* @param plotDimensions The dimensions of the plot
|
|
262
|
-
* @param margin The plot margin
|
|
263
|
-
* @param range The range of the axis (e.g., start and end) in pixels
|
|
264
|
-
* @param axesLabelFont The font for the axis label
|
|
265
|
-
* @param plotDimensions The dimensions of the plot
|
|
266
|
-
* @param margin The plot margin
|
|
267
|
-
* adjust the axis label location when needed
|
|
268
|
-
* @return The number of pixels for each category
|
|
368
|
+
* Removes a category x-axis' draw function from the canvas context (e.g. when the axis unmounts)
|
|
369
|
+
* @param cc The canvas context the axis' draw function is registered with
|
|
370
|
+
* @param axisId The ID of the axis
|
|
269
371
|
*/
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
axesLabelFont, plotDimensions, margin) {
|
|
273
|
-
const updatedRange = AxisInterval.from(Math.min(range.start, 0), Math.max(range.end, plotDimensions.width));
|
|
274
|
-
axis.scale = axis.scale
|
|
275
|
-
.domain(names)
|
|
276
|
-
.range(updatedRange.asTuple());
|
|
277
|
-
axis.categorySize = axis.scale.bandwidth();
|
|
278
|
-
const clipPathId = setClipPath(chartId, axis.axisId, svg, location, plotDimensions, margin);
|
|
279
|
-
axis.selection = axis.selection
|
|
280
|
-
.attr('transform', `translate(${margin.left}, ${yTranslation(location, plotDimensions, margin)})`)
|
|
281
|
-
.attr("clip-path", `url(#${clipPathId})`)
|
|
282
|
-
.call(axis.generator);
|
|
283
|
-
const xLabelTranslation = ordinalLabelXTranslation(location, plotDimensions, margin, axesLabelFont);
|
|
284
|
-
const yLabelTranslation = ordinalLabelYTranslation(location, plotDimensions, margin);
|
|
285
|
-
svg
|
|
286
|
-
.select(`#${labelIdFor(chartId, location)}`)
|
|
287
|
-
.attr('transform', `translate(${xLabelTranslation}, ${yLabelTranslation})`);
|
|
288
|
-
return axis.categorySize;
|
|
372
|
+
export function removeOrdinalXAxis(cc, axisId) {
|
|
373
|
+
cc.unregister(`x-axis-ordinal-${cc.chartId}-${axisId}`);
|
|
289
374
|
}
|
|
290
375
|
/**
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
* @param
|
|
294
|
-
* @param axis The category axis to be updated
|
|
295
|
-
* @param svg The SVG selection (d3)
|
|
296
|
-
* @param location The location of the axis
|
|
297
|
-
* @param names An array holding the category names
|
|
298
|
-
* @param range The range of the axis (e.g. start and end)
|
|
299
|
-
* @param axesLabelFont The font for the axis label
|
|
300
|
-
* @param plotDimensions The dimensions of the plot
|
|
301
|
-
* @param margin The plot margin
|
|
302
|
-
* @param axesLabelFont The font for the axis label
|
|
303
|
-
* @param plotDimensions The dimensions of the plot
|
|
304
|
-
* @param margin The plot margin
|
|
305
|
-
* @return The number of pixels for each category
|
|
376
|
+
* Removes a category y-axis' draw function from the canvas context (e.g. when the axis unmounts)
|
|
377
|
+
* @param cc The canvas context the axis' draw function is registered with
|
|
378
|
+
* @param axisId The ID of the axis
|
|
306
379
|
*/
|
|
307
|
-
function
|
|
308
|
-
|
|
309
|
-
axesLabelFont, plotDimensions, margin) {
|
|
310
|
-
const updatedRange = AxisInterval.from(Math.min(range.start, 0), Math.max(range.end, plotDimensions.height));
|
|
311
|
-
axis.scale = axis.scale
|
|
312
|
-
.domain(names)
|
|
313
|
-
.range(updatedRange.asTuple());
|
|
314
|
-
axis.categorySize = axis.scale.bandwidth();
|
|
315
|
-
axis.selection = axis.selection
|
|
316
|
-
.attr('transform', `translate(${xTranslation(location, plotDimensions, margin)}, ${margin.top})`)
|
|
317
|
-
.call(axis.generator);
|
|
318
|
-
svg
|
|
319
|
-
.select(`#${labelIdFor(chartId, location)}`)
|
|
320
|
-
.attr('transform', `translate(${ordinalLabelXTranslation(location, plotDimensions, margin, axesLabelFont)}, ${ordinalLabelYTranslation(location, plotDimensions, margin)}) rotate(-90)`);
|
|
321
|
-
return axis.categorySize;
|
|
380
|
+
export function removeOrdinalYAxis(cc, axisId) {
|
|
381
|
+
cc.unregister(`y-axis-ordinal-${cc.chartId}-${axisId}`);
|
|
322
382
|
}
|
|
323
383
|
/**
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
* axis
|
|
327
|
-
* @param location The
|
|
384
|
+
* The x-coordinate (in canvas pixels, from the canvas' left edge) of a category axis' label: the
|
|
385
|
+
* label's font size in from the canvas' left or right edge for a y-axis, or the canvas' center for
|
|
386
|
+
* an x-axis
|
|
387
|
+
* @param location The location of the axis
|
|
328
388
|
* @param plotDimensions The dimensions of the plot
|
|
329
|
-
* @param margin The
|
|
389
|
+
* @param margin The plot margin
|
|
330
390
|
* @param axesLabelFont The font for the axis label
|
|
331
|
-
* @return The
|
|
391
|
+
* @return The x-coordinate of the axis label
|
|
332
392
|
*/
|
|
333
393
|
function ordinalLabelXTranslation(location, plotDimensions, margin, axesLabelFont) {
|
|
334
394
|
switch (location) {
|
|
@@ -343,13 +403,12 @@ function ordinalLabelXTranslation(location, plotDimensions, margin, axesLabelFon
|
|
|
343
403
|
}
|
|
344
404
|
}
|
|
345
405
|
/**
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
* @param location The axis location (i.e. top, bottom, left, right)
|
|
406
|
+
* The y-coordinate (in canvas pixels, from the canvas' top edge) of a category axis' label: the
|
|
407
|
+
* canvas' middle for a y-axis, or the canvas' top or bottom edge for an x-axis
|
|
408
|
+
* @param location The location of the axis
|
|
350
409
|
* @param plotDimensions The dimensions of the plot
|
|
351
|
-
* @param margin The
|
|
352
|
-
* @return The
|
|
410
|
+
* @param margin The plot margin
|
|
411
|
+
* @return The y-coordinate of the axis label
|
|
353
412
|
*/
|
|
354
413
|
function ordinalLabelYTranslation(location, plotDimensions, margin) {
|
|
355
414
|
switch (location) {
|
|
@@ -366,261 +425,368 @@ function ordinalLabelYTranslation(location, plotDimensions, margin) {
|
|
|
366
425
|
continuous numeric axes
|
|
367
426
|
*/
|
|
368
427
|
/**
|
|
369
|
-
* Adds a new empty x-axis
|
|
428
|
+
* Adds a new, empty x-axis (a line with no ticks or label) to the canvas context. An empty axis
|
|
370
429
|
* is just a line where the axis would be, without any ticks or labels.
|
|
430
|
+
* @param canvasContext The canvas context to register the axis' draw function with
|
|
371
431
|
* @param axisId The ID of the axis
|
|
372
|
-
* @param svg The SVG selection to which to add the axis
|
|
373
432
|
* @param plotDimensions The dimensions of the plot
|
|
374
433
|
* @param location The location of the axis
|
|
375
|
-
* @param scaleGenerator The
|
|
376
|
-
* @param
|
|
377
|
-
* @param
|
|
378
|
-
* @param
|
|
379
|
-
* @
|
|
434
|
+
* @param scaleGenerator The d3 scale to use for the axis (its domain and range get overwritten)
|
|
435
|
+
* @param margin The plot margins
|
|
436
|
+
* @param setAxisRangeFor A callback used to report the axis' domain when it's updated
|
|
437
|
+
* @param color The color of the axis line (the axis' `updateFont` updates it with the font's color)
|
|
438
|
+
* @param [domain=[0, 1]] The axis' initial domain (min, max)
|
|
439
|
+
* @return A {@link ContinuousNumericAxis} (marked `isEmpty`) based on the arguments to this function
|
|
380
440
|
*/
|
|
381
|
-
export function addEmptyXAxis(
|
|
441
|
+
export function addEmptyXAxis(canvasContext, axisId, plotDimensions, location, scaleGenerator, margin, setAxisRangeFor, color, domain = [0, 1]) {
|
|
382
442
|
const scale = scaleGenerator.domain(domain).range([0, plotDimensions.width]);
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
443
|
+
let currentDimensions = plotDimensions;
|
|
444
|
+
let currentMargin = margin;
|
|
445
|
+
// NOTE: previously this read `ctx.fillStyle` directly, assuming it reflected "the chart's
|
|
446
|
+
// current color". But `ctx` is shared across every draw function registered on the canvas
|
|
447
|
+
// (all axes, all plots, the tracker). Whichever one last set `fillStyle` before this one
|
|
448
|
+
// ran left that value behind. It had nothing to do with this axis' actual color and never
|
|
449
|
+
// updated when the chart's `color`/theme changed, since nothing here ever assigned a new
|
|
450
|
+
// value in response to that. The `currentColor` is now explicit, passed in and refreshable via
|
|
451
|
+
// `updateFont` below.
|
|
452
|
+
let currentColor = color;
|
|
453
|
+
let highlighted = false;
|
|
454
|
+
let highlightColor = defaultLineStyle().highlightColor;
|
|
455
|
+
let highlightLineWidth = defaultLineStyle().highlightWidth;
|
|
456
|
+
const drawHandle = `x-axis-empty-${canvasContext.chartId}-${axisId}`;
|
|
457
|
+
const draw = (context) => {
|
|
458
|
+
const { context2D } = context;
|
|
459
|
+
context2D.save();
|
|
460
|
+
context2D.translate(currentMargin.left, yTranslation(location, currentDimensions, currentMargin));
|
|
461
|
+
context2D.strokeStyle = highlighted ? highlightColor : currentColor;
|
|
462
|
+
context2D.lineWidth = highlighted ? highlightLineWidth : 1;
|
|
463
|
+
context2D.beginPath();
|
|
464
|
+
context2D.moveTo(0, 0);
|
|
465
|
+
context2D.lineTo(currentDimensions.width, 0);
|
|
466
|
+
context2D.stroke();
|
|
467
|
+
context2D.restore();
|
|
468
|
+
};
|
|
469
|
+
canvasContext.register(drawHandle, draw, 0);
|
|
470
|
+
return {
|
|
393
471
|
axisId,
|
|
394
472
|
location,
|
|
395
|
-
|
|
473
|
+
axisType: AxisType.ContinuousNumeric,
|
|
474
|
+
isEmpty: true,
|
|
396
475
|
scale,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
axis.scale.domain(domain.asTuple()).range([0, plotDimensions.width]);
|
|
402
|
-
axis.selection
|
|
403
|
-
.attr('transform', `translate(${margin.left}, ${yTranslation(location, plotDimensions, margin)})`);
|
|
404
|
-
line.attr('x2', plotDimensions.width);
|
|
476
|
+
update: (domain, plotDimensions, margin) => {
|
|
477
|
+
scale.domain(domain.asTuple()).range([0, plotDimensions.width]);
|
|
478
|
+
currentDimensions = plotDimensions;
|
|
479
|
+
currentMargin = margin;
|
|
405
480
|
setAxisRangeFor(axisId, domain);
|
|
406
|
-
|
|
481
|
+
canvasContext.requestRedraw();
|
|
482
|
+
},
|
|
483
|
+
// an empty axis has no ticks or label text but does have a colored line -- reuse
|
|
484
|
+
// updateFont's color field to keep that line in sync with the chart's color (e.g., on a
|
|
485
|
+
// theme change), matching the pattern used by the other axis types
|
|
486
|
+
updateFont: (font) => {
|
|
487
|
+
currentColor = font.color;
|
|
488
|
+
canvasContext.requestRedraw();
|
|
489
|
+
},
|
|
490
|
+
setHighlighted: (isHighlighted, color, lineWidth) => {
|
|
491
|
+
highlighted = isHighlighted;
|
|
492
|
+
if (color !== undefined)
|
|
493
|
+
highlightColor = color;
|
|
494
|
+
if (lineWidth !== undefined)
|
|
495
|
+
highlightLineWidth = lineWidth;
|
|
496
|
+
canvasContext.requestRedraw();
|
|
497
|
+
}
|
|
498
|
+
};
|
|
407
499
|
}
|
|
408
500
|
/**
|
|
409
|
-
* Adds a new empty y-axis
|
|
410
|
-
*
|
|
501
|
+
* Adds a new, empty y-axis (a line with no ticks or label) to the canvas context.
|
|
502
|
+
* @param cc The canvas context to register the axis' draw function with
|
|
411
503
|
* @param axisId The ID of the axis
|
|
412
|
-
* @param svg The SVG selection to which to add the axis
|
|
413
504
|
* @param plotDimensions The dimensions of the plot
|
|
414
505
|
* @param location The location of the axis
|
|
415
|
-
* @param scaleGenerator The
|
|
416
|
-
* @param
|
|
417
|
-
* @param
|
|
418
|
-
* @param
|
|
419
|
-
* @
|
|
506
|
+
* @param scaleGenerator The d3 scale to use for the axis (its domain and range get overwritten)
|
|
507
|
+
* @param margin The plot margins
|
|
508
|
+
* @param setAxisRangeFor A callback used to report the axis' domain when it's updated
|
|
509
|
+
* @param color The color of the axis line (the axis' `updateFont` updates it with the font's color)
|
|
510
|
+
* @param [domain=[0, 1]] The axis' initial domain (min, max)
|
|
511
|
+
* @return A {@link ContinuousNumericAxis} (marked `isEmpty`) based on the arguments to this function
|
|
420
512
|
*/
|
|
421
|
-
export function addEmptyYAxis(
|
|
513
|
+
export function addEmptyYAxis(cc, axisId, plotDimensions, location, scaleGenerator, margin, setAxisRangeFor, color, domain = [0, 1]) {
|
|
422
514
|
const scale = scaleGenerator.domain(domain).range([plotDimensions.height, 0]);
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
515
|
+
let currentDimensions = plotDimensions;
|
|
516
|
+
let currentMargin = margin;
|
|
517
|
+
let currentColor = color;
|
|
518
|
+
let highlighted = false;
|
|
519
|
+
let highlightColor = defaultLineStyle().highlightColor;
|
|
520
|
+
let highlightLineWidth = defaultLineStyle().highlightWidth;
|
|
521
|
+
const drawHandle = `y-axis-empty-${cc.chartId}-${axisId}`;
|
|
522
|
+
const draw = (context) => {
|
|
523
|
+
const { context2D } = context;
|
|
524
|
+
context2D.save();
|
|
525
|
+
context2D.translate(xTranslation(location, currentDimensions, currentMargin), currentMargin.top);
|
|
526
|
+
context2D.strokeStyle = highlighted ? highlightColor : currentColor;
|
|
527
|
+
context2D.lineWidth = highlighted ? highlightLineWidth : 1;
|
|
528
|
+
context2D.beginPath();
|
|
529
|
+
context2D.moveTo(0, 0);
|
|
530
|
+
context2D.lineTo(0, currentDimensions.height);
|
|
531
|
+
context2D.stroke();
|
|
532
|
+
context2D.restore();
|
|
533
|
+
};
|
|
534
|
+
cc.register(drawHandle, draw, 0);
|
|
535
|
+
return {
|
|
433
536
|
axisId,
|
|
434
537
|
location,
|
|
435
|
-
|
|
538
|
+
axisType: AxisType.ContinuousNumeric,
|
|
539
|
+
isEmpty: true,
|
|
436
540
|
scale,
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
axis.scale.domain(domain.asTuple()).range([plotDimensions.height, 0]);
|
|
442
|
-
axis.selection
|
|
443
|
-
.attr('transform', `translate(${xTranslation(location, plotDimensions, margin)}, ${margin.top})`);
|
|
444
|
-
line.attr('y2', plotDimensions.height);
|
|
541
|
+
update: (domain, plotDimensions, margin) => {
|
|
542
|
+
scale.domain(domain.asTuple()).range([plotDimensions.height, 0]);
|
|
543
|
+
currentDimensions = plotDimensions;
|
|
544
|
+
currentMargin = margin;
|
|
445
545
|
setAxisRangeFor(axisId, domain);
|
|
446
|
-
|
|
546
|
+
cc.requestRedraw();
|
|
547
|
+
},
|
|
548
|
+
// an empty axis has no ticks or label text but does have a colored line -- reuse
|
|
549
|
+
// updateFont's color field to keep that line in sync with the chart's color (e.g., on a
|
|
550
|
+
// theme change), matching the pattern used by the other axis types
|
|
551
|
+
updateFont: (font) => {
|
|
552
|
+
currentColor = font.color;
|
|
553
|
+
cc.requestRedraw();
|
|
554
|
+
},
|
|
555
|
+
setHighlighted: (isHighlighted, color, lineWidth) => {
|
|
556
|
+
highlighted = isHighlighted;
|
|
557
|
+
if (color !== undefined)
|
|
558
|
+
highlightColor = color;
|
|
559
|
+
if (lineWidth !== undefined)
|
|
560
|
+
highlightLineWidth = lineWidth;
|
|
561
|
+
cc.requestRedraw();
|
|
562
|
+
}
|
|
563
|
+
};
|
|
447
564
|
}
|
|
448
565
|
/**
|
|
449
|
-
* Adds a new x-axis
|
|
450
|
-
* @param
|
|
451
|
-
* @param axisId
|
|
452
|
-
* @param svg The SVG selection to which to add the axis
|
|
566
|
+
* Adds a new x-axis, registering its draw function with the canvas context.
|
|
567
|
+
* @param cc The canvas context to register the axis' draw function with
|
|
568
|
+
* @param axisId A unique ID for the axis
|
|
453
569
|
* @param plotDimensions The dimensions of the plot
|
|
454
|
-
* @param location The location of the axis
|
|
455
|
-
* @param scaleGenerator The
|
|
456
|
-
* @param domain The axis
|
|
457
|
-
* @param axesLabelFont The font for the axis
|
|
458
|
-
* @param margin The plot margins
|
|
570
|
+
* @param location The location of the axis (top or bottom)
|
|
571
|
+
* @param scaleGenerator The d3 scale to use for the axis (its domain/range get overwritten)
|
|
572
|
+
* @param domain The axis' initial domain (min, max)
|
|
573
|
+
* @param axesLabelFont The font for the axis label and ticks
|
|
574
|
+
* @param margin The plot margins
|
|
459
575
|
* @param axisLabel The label for the axis
|
|
460
|
-
* @param setAxisRangeFor
|
|
461
|
-
* @return A {@link ContinuousNumericAxis}
|
|
576
|
+
* @param setAxisRangeFor Callback used to report the axis' domain when it's updated
|
|
577
|
+
* @return A {@link ContinuousNumericAxis}
|
|
462
578
|
*/
|
|
463
|
-
export function addContinuousNumericXAxis(
|
|
579
|
+
export function addContinuousNumericXAxis(cc, axisId, plotDimensions, location, scaleGenerator, domain, axesLabelFont, margin, axisLabel, setAxisRangeFor) {
|
|
464
580
|
const scale = scaleGenerator.domain(domain).range([0, plotDimensions.width]);
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
.
|
|
476
|
-
.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
.
|
|
480
|
-
|
|
581
|
+
let currentDimensions = plotDimensions;
|
|
582
|
+
let currentMargin = margin;
|
|
583
|
+
const currentLabel = axisLabel;
|
|
584
|
+
let currentFont = axesLabelFont;
|
|
585
|
+
let highlighted = false;
|
|
586
|
+
let highlightColor = defaultLineStyle().highlightColor;
|
|
587
|
+
let highlightLineWidth = defaultLineStyle().highlightWidth;
|
|
588
|
+
const drawHandle = `x-axis-${cc.chartId}-${axisId}`;
|
|
589
|
+
const draw = (context) => {
|
|
590
|
+
const { context2D } = context;
|
|
591
|
+
context2D.save();
|
|
592
|
+
context2D.translate(currentMargin.left, yTranslation(location, currentDimensions, currentMargin));
|
|
593
|
+
// NOTE: the original SVG version never applied a clip-path to the continuous numeric
|
|
594
|
+
// axes (only the ordinal/category axes clip), which let the first/last tick labels
|
|
595
|
+
// overflow into the margin without being cut off. Clipping to exactly the plot width
|
|
596
|
+
// here would chop those end labels in half, so ticks/labels are intentionally unclipped.
|
|
597
|
+
const axisColor = highlighted ? highlightColor : currentFont.color;
|
|
598
|
+
context2D.strokeStyle = axisColor;
|
|
599
|
+
context2D.fillStyle = axisColor;
|
|
600
|
+
context2D.lineWidth = highlighted ? highlightLineWidth : 1;
|
|
601
|
+
context2D.font = fontStringFor(currentFont.size, currentFont.family, currentFont.weight);
|
|
602
|
+
context2D.textAlign = 'center';
|
|
603
|
+
context2D.textBaseline = location === AxisLocation.Bottom ? 'top' : 'bottom';
|
|
604
|
+
// domain line
|
|
605
|
+
context2D.beginPath();
|
|
606
|
+
context2D.moveTo(0, 0);
|
|
607
|
+
context2D.lineTo(currentDimensions.width, 0);
|
|
608
|
+
context2D.stroke();
|
|
609
|
+
// ticks
|
|
610
|
+
const tickDirection = location === AxisLocation.Bottom ? 1 : -1;
|
|
611
|
+
scale.ticks().forEach(tickValue => {
|
|
612
|
+
const x = scale(tickValue);
|
|
613
|
+
context2D.beginPath();
|
|
614
|
+
context2D.moveTo(x, 0);
|
|
615
|
+
context2D.lineTo(x, TICK_SIZE * tickDirection);
|
|
616
|
+
context2D.stroke();
|
|
617
|
+
context2D.fillText(scale.tickFormat()(tickValue), x, (TICK_SIZE + TICK_PADDING) * tickDirection);
|
|
618
|
+
});
|
|
619
|
+
// axis label (not clipped, matches the old behavior)
|
|
620
|
+
context2D.fillStyle = axisColor;
|
|
621
|
+
context2D.font = fontStringFor(currentFont.size, currentFont.family, currentFont.weight);
|
|
622
|
+
context2D.textAlign = 'center';
|
|
623
|
+
// (a bottom label sits on the canvas' bottom edge, so it's drawn above it, descenders and all)
|
|
624
|
+
context2D.textBaseline = location === AxisLocation.Top ? 'hanging' : 'bottom';
|
|
625
|
+
const labelY = continuousLabelYTranslation(location, currentDimensions, currentMargin) - yTranslation(location, currentDimensions, currentMargin);
|
|
626
|
+
context2D.fillText(currentLabel, currentDimensions.width / 2, labelY);
|
|
627
|
+
context2D.restore();
|
|
628
|
+
};
|
|
629
|
+
cc.register(drawHandle, draw, 0);
|
|
630
|
+
return {
|
|
481
631
|
axisId,
|
|
482
632
|
location,
|
|
483
|
-
|
|
633
|
+
axisType: AxisType.ContinuousNumeric,
|
|
484
634
|
scale,
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
updateLinearXAxis(domain, axisLabel, chartId, svg, axis, plotDimensions, margin, location);
|
|
635
|
+
update: (domain, plotDimensions, margin) => {
|
|
636
|
+
scale.domain(domain.asTuple()).range([0, plotDimensions.width]);
|
|
637
|
+
currentDimensions = plotDimensions;
|
|
638
|
+
currentMargin = margin;
|
|
490
639
|
setAxisRangeFor(axisId, domain);
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
axis.selection
|
|
507
|
-
.attr('transform', `translate(${margin.left}, ${yTranslation(location, plotDimensions, margin)})`)
|
|
508
|
-
.call(axis.generator);
|
|
509
|
-
svg
|
|
510
|
-
.select(`#${labelIdFor(chartId, location)}`)
|
|
511
|
-
.attr('transform', `translate(${margin.left + plotDimensions.width / 2}, ${continuousLabelYTranslation(location, plotDimensions, margin)})`)
|
|
512
|
-
.text(label);
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* The number of pixels to translate the x-axis label to the right
|
|
516
|
-
* @param location The location of the x-axis
|
|
517
|
-
* @param plotDimensions The dimensions of the plot
|
|
518
|
-
* @param margin The plot margins for the border of main SVG group
|
|
519
|
-
* @return The number of pixels to translate the x-axis label to the right
|
|
520
|
-
*/
|
|
521
|
-
function continuousLabelYTranslation(location, plotDimensions, margin) {
|
|
522
|
-
return location === AxisLocation.Bottom ? plotDimensions.height + margin.top + margin.bottom : 0;
|
|
640
|
+
cc.requestRedraw();
|
|
641
|
+
},
|
|
642
|
+
updateFont: (font) => {
|
|
643
|
+
currentFont = font;
|
|
644
|
+
cc.requestRedraw();
|
|
645
|
+
},
|
|
646
|
+
setHighlighted: (isHighlighted, color, lineWidth) => {
|
|
647
|
+
highlighted = isHighlighted;
|
|
648
|
+
if (color !== undefined)
|
|
649
|
+
highlightColor = color;
|
|
650
|
+
if (lineWidth !== undefined)
|
|
651
|
+
highlightLineWidth = lineWidth;
|
|
652
|
+
cc.requestRedraw();
|
|
653
|
+
}
|
|
654
|
+
};
|
|
523
655
|
}
|
|
524
656
|
/**
|
|
525
|
-
* Adds a new y-axis
|
|
526
|
-
* @param
|
|
527
|
-
* @param axisId
|
|
528
|
-
* @param svg The SVG selection to which to add the axis
|
|
657
|
+
* Adds a new y-axis, registering its draw function with the canvas context.
|
|
658
|
+
* @param cc The canvas context to register the axis' draw function with
|
|
659
|
+
* @param axisId A unique ID for the axis
|
|
529
660
|
* @param plotDimensions The dimensions of the plot
|
|
530
|
-
* @param location The location of the axis
|
|
531
|
-
* @param scaleGenerator The
|
|
532
|
-
* @param domain The axis
|
|
533
|
-
* @param axesLabelFont The font for the axis
|
|
534
|
-
* @param margin The plot margins
|
|
661
|
+
* @param location The location of the axis (left or right)
|
|
662
|
+
* @param scaleGenerator The d3 scale to use for the axis (its domain/range get overwritten)
|
|
663
|
+
* @param domain The axis' initial domain (min, max)
|
|
664
|
+
* @param axesLabelFont The font for the axis label and ticks
|
|
665
|
+
* @param margin The plot margins
|
|
535
666
|
* @param axisLabel The label for the axis
|
|
536
|
-
* @param setAxisRangeFor
|
|
537
|
-
* @return A {@link ContinuousNumericAxis}
|
|
667
|
+
* @param setAxisRangeFor Callback used to report the axis' domain when it's updated
|
|
668
|
+
* @return A {@link ContinuousNumericAxis}
|
|
538
669
|
*/
|
|
539
|
-
export function addContinuousNumericYAxis(
|
|
670
|
+
export function addContinuousNumericYAxis(cc, axisId, plotDimensions, location, scaleGenerator, domain, axesLabelFont, margin, axisLabel, setAxisRangeFor) {
|
|
540
671
|
const scale = scaleGenerator
|
|
541
672
|
.domain(domain)
|
|
542
673
|
.range([Math.max(margin.bottom, plotDimensions.height), 0]);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
.
|
|
554
|
-
.
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
674
|
+
let currentDimensions = plotDimensions;
|
|
675
|
+
let currentMargin = margin;
|
|
676
|
+
const currentLabel = axisLabel;
|
|
677
|
+
let currentFont = axesLabelFont;
|
|
678
|
+
let highlighted = false;
|
|
679
|
+
let highlightColor = defaultLineStyle().highlightColor;
|
|
680
|
+
let highlightLineWidth = defaultLineStyle().highlightWidth;
|
|
681
|
+
const drawHandle = `y-axis-${cc.chartId}-${axisId}`;
|
|
682
|
+
const draw = (context) => {
|
|
683
|
+
const { context2D } = context;
|
|
684
|
+
context2D.save();
|
|
685
|
+
context2D.translate(xTranslation(location, currentDimensions, currentMargin), currentMargin.top);
|
|
686
|
+
// NOTE: unclipped, matching the old SVG version's continuous numeric axes (only the
|
|
687
|
+
// ordinal/category axes clipped there) -- clipping to exactly the plot height would cut
|
|
688
|
+
// off the top- and bottom-most tick labels, which straddle y=0 and y=height.
|
|
689
|
+
const axisColor = highlighted ? highlightColor : currentFont.color;
|
|
690
|
+
context2D.strokeStyle = axisColor;
|
|
691
|
+
context2D.fillStyle = axisColor;
|
|
692
|
+
context2D.lineWidth = highlighted ? highlightLineWidth : 1;
|
|
693
|
+
context2D.font = fontStringFor(currentFont.size, currentFont.family, currentFont.weight);
|
|
694
|
+
context2D.textBaseline = 'middle';
|
|
695
|
+
context2D.textAlign = location === AxisLocation.Left ? 'right' : 'left';
|
|
696
|
+
// domain line
|
|
697
|
+
context2D.beginPath();
|
|
698
|
+
context2D.moveTo(0, 0);
|
|
699
|
+
context2D.lineTo(0, currentDimensions.height);
|
|
700
|
+
context2D.stroke();
|
|
701
|
+
// ticks
|
|
702
|
+
const tickDirection = location === AxisLocation.Left ? -1 : 1;
|
|
703
|
+
scale.ticks().forEach(tickValue => {
|
|
704
|
+
const y = scale(tickValue);
|
|
705
|
+
context2D.beginPath();
|
|
706
|
+
context2D.moveTo(0, y);
|
|
707
|
+
context2D.lineTo(TICK_SIZE * tickDirection, y);
|
|
708
|
+
context2D.stroke();
|
|
709
|
+
context2D.fillText(scale.tickFormat()(tickValue), (TICK_SIZE + TICK_PADDING) * tickDirection, y);
|
|
710
|
+
});
|
|
711
|
+
// axis label, rotated -90deg, matching the old SVG version
|
|
712
|
+
context2D.save();
|
|
713
|
+
const labelX = continuousLabelXTranslation(location, currentDimensions, currentMargin, currentFont) - xTranslation(location, currentDimensions, currentMargin);
|
|
714
|
+
context2D.translate(labelX, currentDimensions.height / 2);
|
|
715
|
+
context2D.rotate(-Math.PI / 2);
|
|
716
|
+
context2D.fillStyle = axisColor;
|
|
717
|
+
context2D.font = fontStringFor(currentFont.size, currentFont.family, currentFont.weight);
|
|
718
|
+
context2D.textAlign = 'center';
|
|
719
|
+
context2D.textBaseline = 'alphabetic';
|
|
720
|
+
context2D.fillText(currentLabel, 0, 0);
|
|
721
|
+
context2D.restore();
|
|
722
|
+
context2D.restore();
|
|
723
|
+
};
|
|
724
|
+
cc.register(drawHandle, draw, 0);
|
|
725
|
+
return {
|
|
558
726
|
axisId,
|
|
559
727
|
location,
|
|
560
|
-
|
|
728
|
+
axisType: AxisType.ContinuousNumeric,
|
|
561
729
|
scale,
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
updateLinearYAxis(domain, axisLabel, chartId, svg, axis, plotDimensions, margin, axesLabelFont, location);
|
|
730
|
+
update: (domain, plotDimensions, margin) => {
|
|
731
|
+
scale.domain(domain.asTuple()).range([Math.max(margin.bottom, plotDimensions.height), 0]);
|
|
732
|
+
currentDimensions = plotDimensions;
|
|
733
|
+
currentMargin = margin;
|
|
567
734
|
setAxisRangeFor(axisId, domain);
|
|
568
|
-
|
|
735
|
+
cc.requestRedraw();
|
|
736
|
+
},
|
|
737
|
+
updateFont: (font) => {
|
|
738
|
+
currentFont = font;
|
|
739
|
+
cc.requestRedraw();
|
|
740
|
+
},
|
|
741
|
+
setHighlighted: (isHighlighted, color, lineWidth) => {
|
|
742
|
+
highlighted = isHighlighted;
|
|
743
|
+
if (color !== undefined)
|
|
744
|
+
highlightColor = color;
|
|
745
|
+
if (lineWidth !== undefined)
|
|
746
|
+
highlightLineWidth = lineWidth;
|
|
747
|
+
cc.requestRedraw();
|
|
748
|
+
}
|
|
749
|
+
};
|
|
569
750
|
}
|
|
570
751
|
/**
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
* @param
|
|
574
|
-
* @param
|
|
575
|
-
* @param svg The SVG selection of which the axis is a child node
|
|
576
|
-
* @param axis The y-axis
|
|
577
|
-
* @param plotDimensions The dimensions of the plot
|
|
578
|
-
* @param margin The plot margins for the border of main SVG group
|
|
579
|
-
* @param axesLabelFont The font for the axis label
|
|
580
|
-
* @param location The location of the axis (i.e. top, bottom, left, right)
|
|
752
|
+
* Removes a continuous x-axis' draw function from the canvas context (called on "unmount" to avoid
|
|
753
|
+
* leaking a draw registration for an axis that's no longer part of the chart).
|
|
754
|
+
* @param cc The canvas context the axis' draw function is registered with
|
|
755
|
+
* @param axisId The ID of the axis
|
|
581
756
|
*/
|
|
582
|
-
function
|
|
583
|
-
|
|
584
|
-
axis.selection
|
|
585
|
-
.attr('transform', `translate(${xTranslation(location, plotDimensions, margin)}, ${margin.top})`)
|
|
586
|
-
.call(axis.generator);
|
|
587
|
-
svg
|
|
588
|
-
.select(`#${labelIdFor(chartId, location)}`)
|
|
589
|
-
.attr('transform', `translate(${continuousLabelXTranslation(location, plotDimensions, margin, axesLabelFont)}, ${margin.top + plotDimensions.height / 2}) rotate(-90)`)
|
|
590
|
-
.text(label);
|
|
757
|
+
export function removeContinuousXAxis(cc, axisId) {
|
|
758
|
+
cc.unregister(`x-axis-${cc.chartId}-${axisId}`);
|
|
591
759
|
}
|
|
592
760
|
/**
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
* @param
|
|
596
|
-
* @param
|
|
597
|
-
* @param axesLabelFont The font for the axis label
|
|
598
|
-
* @return The number of pixels to translate the y-axis label down
|
|
761
|
+
* Removes a continuous y-axis' draw function from the canvas context (called on "unmount" to avoid
|
|
762
|
+
* leaking a draw registration for an axis that's no longer part of the chart).
|
|
763
|
+
* @param cc The canvas context the axis' draw function is registered with
|
|
764
|
+
* @param axisId The ID of the axis
|
|
599
765
|
*/
|
|
600
|
-
function
|
|
601
|
-
|
|
602
|
-
axesLabelFont.size :
|
|
603
|
-
margin.left + plotDimensions.width + margin.right - axesLabelFont.size;
|
|
766
|
+
export function removeContinuousYAxis(cc, axisId) {
|
|
767
|
+
cc.unregister(`y-axis-${cc.chartId}-${axisId}`);
|
|
604
768
|
}
|
|
605
769
|
/*
|
|
606
770
|
common axis functions
|
|
607
771
|
*/
|
|
608
772
|
/**
|
|
609
|
-
*
|
|
610
|
-
*
|
|
773
|
+
* The x-coordinate (in canvas pixels) of a y-axis' line: the plot's left edge for a left axis, or
|
|
774
|
+
* its right edge for a right axis
|
|
775
|
+
* @param location The location of the axis
|
|
611
776
|
* @param plotDimensions The dimensions of the plot
|
|
612
|
-
* @param margin The
|
|
613
|
-
* @return The
|
|
777
|
+
* @param margin The plot margin
|
|
778
|
+
* @return The x-coordinate of the axis line
|
|
614
779
|
*/
|
|
615
780
|
function xTranslation(location, plotDimensions, margin) {
|
|
616
781
|
return location === AxisLocation.Left ? margin.left : margin.left + plotDimensions.width;
|
|
617
782
|
}
|
|
618
783
|
/**
|
|
619
|
-
* The
|
|
620
|
-
*
|
|
784
|
+
* The y-coordinate (in canvas pixels) of an x-axis' line: the plot's bottom edge for a bottom
|
|
785
|
+
* axis, or its top edge for a top axis
|
|
786
|
+
* @param location The location of the axis
|
|
621
787
|
* @param plotDimensions The dimensions of the plot
|
|
622
|
-
* @param margin The plot
|
|
623
|
-
* @return The
|
|
788
|
+
* @param margin The plot margin
|
|
789
|
+
* @return The y-coordinate of the axis line
|
|
624
790
|
*/
|
|
625
791
|
function yTranslation(location, plotDimensions, margin) {
|
|
626
792
|
return location === AxisLocation.Bottom ?
|
|
@@ -628,92 +794,88 @@ function yTranslation(location, plotDimensions, margin) {
|
|
|
628
794
|
margin.top;
|
|
629
795
|
}
|
|
630
796
|
/**
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
* @param location The
|
|
634
|
-
* @
|
|
797
|
+
* The y-coordinate (in canvas pixels) of a continuous x-axis' label: the canvas' bottom edge for
|
|
798
|
+
* a bottom axis, or its top edge for a top axis
|
|
799
|
+
* @param location The location of the axis
|
|
800
|
+
* @param plotDimensions The dimensions of the plot
|
|
801
|
+
* @param margin The plot margin
|
|
802
|
+
* @return The y-coordinate of the axis label
|
|
635
803
|
*/
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
804
|
+
function continuousLabelYTranslation(location, plotDimensions, margin) {
|
|
805
|
+
return location === AxisLocation.Bottom ? plotDimensions.height + margin.top + margin.bottom : 0;
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* The x-coordinate (in canvas pixels) of a continuous y-axis' label: the label's font size in from
|
|
809
|
+
* the canvas' left edge for a left axis, or from its right edge for a right axis
|
|
810
|
+
* @param location The location of the axis
|
|
811
|
+
* @param plotDimensions The dimensions of the plot
|
|
812
|
+
* @param margin The plot margin
|
|
813
|
+
* @param axesLabelFont The font for the axis label
|
|
814
|
+
* @return The x-coordinate of the axis label
|
|
815
|
+
*/
|
|
816
|
+
function continuousLabelXTranslation(location, plotDimensions, margin, axesLabelFont) {
|
|
817
|
+
return location === AxisLocation.Left ?
|
|
818
|
+
axesLabelFont.size :
|
|
819
|
+
margin.left + plotDimensions.width + margin.right - axesLabelFont.size;
|
|
645
820
|
}
|
|
646
|
-
// /**
|
|
647
|
-
// * todo this can be generalized to any continuous numeric axis, replace x with value
|
|
648
|
-
// * Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out. Zooms in/out
|
|
649
|
-
// * at the location of the mouse when the scroll wheel or gesture was applied.
|
|
650
|
-
// * @param transform The d3 zoom transformation information
|
|
651
|
-
// * @param x The x-position of the mouse when the scroll wheel or gesture is used
|
|
652
|
-
// * @param axis The axis being zoomed
|
|
653
|
-
// * @param range The current range for the axis being zoomed
|
|
654
|
-
// * @return The updated range and the new zoom factor
|
|
655
|
-
// */
|
|
656
|
-
// // export function calculateZoomFor<AR extends BaseAxisRange>(
|
|
657
|
-
// export function calculateZoomFor(
|
|
658
|
-
// transform: ZoomTransform,
|
|
659
|
-
// x: number,
|
|
660
|
-
// axis: ContinuousNumericAxis,
|
|
661
|
-
// range: ContinuousAxisRange,
|
|
662
|
-
// ): ZoomResult<ContinuousAxisRange> {
|
|
663
|
-
// const time = axis.generator.scale<ScaleLinear<number, number>>().invert(x);
|
|
664
|
-
// return {
|
|
665
|
-
// range: range.scale(transform.k, time),
|
|
666
|
-
// zoomFactor: transform.k
|
|
667
|
-
// } as ZoomResult<ContinuousAxisRange>
|
|
668
|
-
// }
|
|
669
821
|
/**
|
|
670
822
|
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out. Zooms in/out
|
|
671
|
-
*
|
|
672
|
-
* the
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
823
|
+
* around the specified domain value (the pivot), while ensuring that the range (start, end) is
|
|
824
|
+
* contained within the constraint (min, max). The pivot is a domain value rather than a pixel
|
|
825
|
+
* position -- while streaming, callers pin it to the axis's current "now" rather than to wherever
|
|
826
|
+
* the mouse happens to be (see `calcZoomAndUpdate`'s `pivotDomainValueFor`), which is what keeps
|
|
827
|
+
* "now" fixed on screen as the zoom widens/narrows the window around it.
|
|
828
|
+
*
|
|
829
|
+
* `zoomFactor` is *incremental* (relative to the range's `.current`, not its `.original`) -- see
|
|
830
|
+
* {@link BaseAxisRange.scaledRange}. d3-zoom's own `transform.k` is cumulative from wherever
|
|
831
|
+
* `__zoom` was last reset to identity, so callers must convert it to an incremental factor (this
|
|
832
|
+
* event's `k` divided by the previously-applied `k`) before calling this -- see
|
|
833
|
+
* `useCanvasZoomPan`.
|
|
834
|
+
* @param zoomFactor The incremental zoom scale factor for this event
|
|
835
|
+
* @param domainValue The domain value to zoom around (the pivot)
|
|
676
836
|
* @param range The current range for the axis being zoomed
|
|
677
837
|
* @param constraint The minimum and maximum value the scaled range can have
|
|
678
|
-
* @return The updated range
|
|
838
|
+
* @return The updated range
|
|
679
839
|
*/
|
|
680
|
-
export function calculateConstrainedZoomFor(
|
|
681
|
-
const domainValue = axis.generator.scale().invert(x);
|
|
840
|
+
export function calculateConstrainedZoomFor(zoomFactor, domainValue, range, constraint) {
|
|
682
841
|
return {
|
|
683
|
-
range: range.constrainedScale(
|
|
684
|
-
zoomFactor: transform.k
|
|
842
|
+
range: range.constrainedScale(zoomFactor, domainValue, constraint),
|
|
685
843
|
};
|
|
686
844
|
}
|
|
687
845
|
/**
|
|
688
|
-
* Calculates the zoom for an ordinal axis.
|
|
689
|
-
*
|
|
846
|
+
* Calculates the zoom for an ordinal axis. Unlike {@link calculateConstrainedZoomFor}'s continuous
|
|
847
|
+
* axis, `zoomFactor` here is *cumulative* (d3-zoom's own `event.transform.k`, passed through
|
|
848
|
+
* unmodified) -- see {@link OrdinalAxisRange.scaledCumulative} for why: the range is scaled from
|
|
849
|
+
* `.current` by the incremental step the cumulative factor implies, except that a factor of
|
|
850
|
+
* exactly 1 snaps it back to `.original`, so that zooming all the way out always shows every
|
|
851
|
+
* category, whatever pivots were used along the way.
|
|
852
|
+
* @param zoomFactor The cumulative zoom scale factor for this event
|
|
690
853
|
* @param x The x-position of the mouse when the scroll wheel or gesture is used
|
|
691
854
|
* @param range The current range for the axis being zoomed
|
|
692
855
|
* @param constraint The minimum and maximum value the scaled range can have
|
|
693
|
-
* @return A ZoomResult holding the updated range
|
|
856
|
+
* @return A ZoomResult holding the updated range
|
|
694
857
|
*/
|
|
695
|
-
export function calculateOrdinalConstrainedZoomFor(
|
|
696
|
-
const updatedRange = range.constrainedScale(transform.k, x, constraint);
|
|
697
|
-
const k = range.original.equals(updatedRange.original) ? 1 : transform.k;
|
|
858
|
+
export function calculateOrdinalConstrainedZoomFor(zoomFactor, x, range, constraint) {
|
|
698
859
|
return {
|
|
699
|
-
range:
|
|
700
|
-
zoomFactor: k
|
|
860
|
+
range: range.constrainedScale(zoomFactor, x, constraint),
|
|
701
861
|
};
|
|
702
862
|
}
|
|
703
863
|
/*
|
|
704
864
|
panning
|
|
705
865
|
*/
|
|
706
866
|
/**
|
|
707
|
-
*
|
|
708
|
-
*
|
|
709
|
-
* @param
|
|
710
|
-
* @param
|
|
867
|
+
* Calculates the axis range after the plot is dragged to the left or right (x-axis) or up or down
|
|
868
|
+
* (y-axis).
|
|
869
|
+
* @param delta The amount (in pixels) that the plot is dragged
|
|
870
|
+
* @param axis The axis being panned
|
|
871
|
+
* @param range The current range for the axis being panned
|
|
711
872
|
* @param [constrainToOriginalRange=false] When set to `true` then the pan requires that the axis
|
|
712
|
-
* range remains a subset of the
|
|
873
|
+
* range remains a subset of the original axis range (a pan that would leave it isn't made); when
|
|
874
|
+
* `false` the pan allows any range
|
|
713
875
|
* @return The updated range
|
|
714
876
|
*/
|
|
715
877
|
export function calculatePanFor(delta, axis, range, constrainToOriginalRange = false) {
|
|
716
|
-
const scale = axis.
|
|
878
|
+
const scale = axis.scale;
|
|
717
879
|
const value = scale(range.current.start);
|
|
718
880
|
if (value !== undefined) {
|
|
719
881
|
const deltaValue = scale.invert(value + delta) - range.current.start;
|
|
@@ -724,32 +886,45 @@ export function calculatePanFor(delta, axis, range, constrainToOriginalRange = f
|
|
|
724
886
|
}
|
|
725
887
|
return range;
|
|
726
888
|
}
|
|
727
|
-
|
|
889
|
+
/**
|
|
890
|
+
* Calculates the ordinal axis range after the plot is dragged to the left or right (x-axis) or up
|
|
891
|
+
* or down (y-axis). A pan that would leave part of the plot without categories (i.e. take the
|
|
892
|
+
* range's start past 0, or its end short of the plot's width or height) isn't made.
|
|
893
|
+
* @param delta The amount (in pixels) to pan the axis by.
|
|
894
|
+
* @param range The current axis range.
|
|
895
|
+
* @param plotDimensions The dimensions of the plot.
|
|
896
|
+
* @param location The location of the axis.
|
|
897
|
+
* @param constrainToOriginalRange Whether to constrain the pan to the original range.
|
|
898
|
+
* @returns The new axis range.
|
|
899
|
+
*/
|
|
900
|
+
export function calculateOrdinalPanFor(delta, range, plotDimensions, location, constrainToOriginalRange = false) {
|
|
728
901
|
const constraint = constrainToOriginalRange ?
|
|
729
902
|
range.original.asTuple() :
|
|
730
903
|
[-Infinity, Infinity];
|
|
731
|
-
//
|
|
732
|
-
//
|
|
733
|
-
|
|
904
|
+
// the axis's pixel extent depends on its location: a top/bottom (x) axis spans the plot's
|
|
905
|
+
// width, while a left/right (y) axis spans the plot's height
|
|
906
|
+
const extent = location === AxisLocation.Top || location === AxisLocation.Bottom ?
|
|
907
|
+
plotDimensions.width :
|
|
908
|
+
plotDimensions.height;
|
|
909
|
+
// only allow panning if the plot dimensions (i.e. [0, extent]) is in the current axis range
|
|
910
|
+
if (range.current.start + delta > 0 || range.current.end + delta < extent) {
|
|
734
911
|
return range;
|
|
735
912
|
}
|
|
736
913
|
return range.translate(delta, constraint);
|
|
737
914
|
}
|
|
738
|
-
/*
|
|
739
|
-
|
|
740
|
-
*/
|
|
741
915
|
/**
|
|
742
916
|
* Accepts the series, the assignment of the series to axes, and the current x-axes state, and
|
|
743
|
-
* returns an array of the distinct axis IDs that cover all the series in the plot
|
|
917
|
+
* returns an array of the distinct x-axis IDs that cover all the series in the plot (a series
|
|
918
|
+
* without an x-axis assignment uses the default x-axis).
|
|
744
919
|
*
|
|
745
920
|
* @param series The array of series
|
|
746
921
|
* @param axisAssignments A map association a series name with its axis assignments
|
|
747
|
-
* @param axesState The current
|
|
748
|
-
* @return an array of the distinct
|
|
922
|
+
* @param axesState The current x-axes state
|
|
923
|
+
* @return an array of the distinct x-axis IDs that cover all the series in the plot
|
|
749
924
|
*/
|
|
750
925
|
export function axesForSeriesGen(series, axisAssignments, axesState) {
|
|
751
926
|
return series.map(srs => srs.name)
|
|
752
|
-
// grab the x-axis assigned to the series
|
|
927
|
+
// grab the x-axis assigned to the series or use the default x-axis if not
|
|
753
928
|
// assignment has been made
|
|
754
929
|
.map(name => { var _a; return ((_a = axisAssignments.get(name)) === null || _a === void 0 ? void 0 : _a.xAxis) || axesState.axisDefaultId().getOrElse(""); })
|
|
755
930
|
// de-dup the array of axis IDs so that we don't end up applying the pan or zoom
|
|
@@ -807,12 +982,13 @@ function ordinalPanAxes(delta, axesForSeries, axesState, ranges, setAxisRange, p
|
|
|
807
982
|
const currentRange = ranges.get(axisId);
|
|
808
983
|
if (currentRange && axis) {
|
|
809
984
|
// calculate the change in the axis-range based on the pixel change from the drag event
|
|
810
|
-
const range = calculateOrdinalPanFor(delta, currentRange, plotDimensions, constrainToOriginalRange);
|
|
985
|
+
const range = calculateOrdinalPanFor(delta, currentRange, plotDimensions, axis.location, constrainToOriginalRange);
|
|
811
986
|
// update the time-range for the axis
|
|
812
987
|
ranges.set(axisId, range);
|
|
813
988
|
setAxisRange(axisId, range.current);
|
|
814
|
-
// update the axis' time-range
|
|
815
|
-
axis
|
|
989
|
+
// update the axis' time-range -- panning never changes the set of categories, so
|
|
990
|
+
// pass the axis's own current domain back unchanged
|
|
991
|
+
axis.update(axis.scale.domain(), range.current, range.original, plotDimensions, margin);
|
|
816
992
|
}
|
|
817
993
|
});
|
|
818
994
|
});
|
|
@@ -824,7 +1000,7 @@ function ordinalPanAxes(delta, axesForSeries, axesState, ranges, setAxisRange, p
|
|
|
824
1000
|
* to the left or right. After calling the handler function, the plot needs to be updated as well, and this is
|
|
825
1001
|
* left for the caller.
|
|
826
1002
|
*
|
|
827
|
-
* Please note that the function generated by this function has side effects -- it updates the
|
|
1003
|
+
* Please note that the function generated by this function has side effects -- it updates the axis ranges.
|
|
828
1004
|
*
|
|
829
1005
|
* @param axesForSeries The distinct axes that cover all the series
|
|
830
1006
|
* @param margin The plot margin
|
|
@@ -837,13 +1013,11 @@ function ordinalPanAxes(delta, axesForSeries, axesState, ranges, setAxisRange, p
|
|
|
837
1013
|
export function panHandler(axesForSeries, margin, setAxisRangeFor, axesState, constrainToOriginalRange = false) {
|
|
838
1014
|
/**
|
|
839
1015
|
* Adjusts the time-range and updates the plot when the plot is dragged to the left or right
|
|
840
|
-
* @param
|
|
1016
|
+
* @param delta The amount that the plot is dragged
|
|
841
1017
|
* @param plotDimensions The dimensions of the plot
|
|
842
|
-
* @param series An array of series names
|
|
843
1018
|
* @param ranges A map holding the axis ID and its associated time range
|
|
844
1019
|
*/
|
|
845
1020
|
return (delta, plotDimensions, ranges) => {
|
|
846
|
-
// return (delta: number, plotDimensions: Dimensions, series: Array<string>, ranges: Map<string, ContinuousAxisRange>) => {
|
|
847
1021
|
// run through the axis IDs, adjust their domain, and update the time-range set for that axis
|
|
848
1022
|
panAxes(delta, axesForSeries, axesState, ranges, setAxisRangeFor, plotDimensions, margin, constrainToOriginalRange);
|
|
849
1023
|
// hey, don't forget to update the plot with the new time-ranges in the code calling this... :)
|
|
@@ -856,7 +1030,7 @@ export function panHandler(axesForSeries, margin, setAxisRangeFor, axesState, co
|
|
|
856
1030
|
* to the left or right. After calling the handler function, the plot needs to be updated as well, and this is
|
|
857
1031
|
* left for the caller.
|
|
858
1032
|
*
|
|
859
|
-
* Please note that the function generated by this function has side effects -- it updates the axes ranges.
|
|
1033
|
+
* Please note that the function generated by this function has side effects -- it updates the axes' ranges.
|
|
860
1034
|
*
|
|
861
1035
|
* @param axesForSeries The distinct axes that cover all the series
|
|
862
1036
|
* @param margin The plot margin
|
|
@@ -869,12 +1043,12 @@ export function panHandler(axesForSeries, margin, setAxisRangeFor, axesState, co
|
|
|
869
1043
|
export function ordinalPanHandler(axesForSeries, margin, setAxisRangeFor, axesState, constrainToOriginalRange = false) {
|
|
870
1044
|
/**
|
|
871
1045
|
* Adjusts the time-range and updates the plot when the plot is dragged to the left or right
|
|
872
|
-
* @param
|
|
1046
|
+
* @param delta The amount that the plot is dragged
|
|
873
1047
|
* @param plotDimensions The dimensions of the plot
|
|
874
|
-
* @param
|
|
1048
|
+
* @param _series An array of series names
|
|
875
1049
|
* @param ranges A map holding the axis ID and its associated time range
|
|
876
1050
|
*/
|
|
877
|
-
return (delta, plotDimensions,
|
|
1051
|
+
return (delta, plotDimensions, _series, ranges) => {
|
|
878
1052
|
// run through the axis IDs, adjust their domain, and update the time-range set for that axis
|
|
879
1053
|
ordinalPanAxes(delta, axesForSeries, axesState, ranges, setAxisRangeFor, plotDimensions, margin, constrainToOriginalRange);
|
|
880
1054
|
// hey, don't forget to update the plot with the new ranges in the code calling this... :)
|
|
@@ -887,7 +1061,7 @@ export function ordinalPanHandler(axesForSeries, margin, setAxisRangeFor, axesSt
|
|
|
887
1061
|
* to the left or right. After calling the handler function, the plot needs to be updated as well, and this is
|
|
888
1062
|
* left for the caller.
|
|
889
1063
|
*
|
|
890
|
-
* Please note that the function generated by this function has side effects -- it updates the axes ranges.
|
|
1064
|
+
* Please note that the function generated by this function has side effects -- it updates the axes' ranges.
|
|
891
1065
|
*
|
|
892
1066
|
* @param xAxesForSeries The distinct x-axes that cover all the series
|
|
893
1067
|
* @param yAxesForSeries The distinct y-axes that cover all the series
|
|
@@ -902,12 +1076,14 @@ export function ordinalPanHandler(axesForSeries, margin, setAxisRangeFor, axesSt
|
|
|
902
1076
|
export function panHandler2D(xAxesForSeries, yAxesForSeries, margin, setAxisRange, xAxesState, yAxesState, constrainToOriginalRange = true) {
|
|
903
1077
|
/**
|
|
904
1078
|
* Adjusts the time-range and updates the plot when the plot is dragged to the left or right
|
|
905
|
-
* @param deltaX The amount that the plot is dragged
|
|
1079
|
+
* @param deltaX The amount that the plot is dragged in x
|
|
1080
|
+
* @param deltaY The amount that the plot is dragged in y
|
|
906
1081
|
* @param plotDimensions The dimensions of the plot
|
|
907
|
-
* @param
|
|
908
|
-
* @param
|
|
1082
|
+
* @param _series An array of series names
|
|
1083
|
+
* @param xRanges A map holding the x-axis ID and its associated time range
|
|
1084
|
+
* @param yRanges A map holding the y-axis ID and its associated time range
|
|
909
1085
|
*/
|
|
910
|
-
return (deltaX, deltaY, plotDimensions,
|
|
1086
|
+
return (deltaX, deltaY, plotDimensions, _series, xRanges, yRanges) => {
|
|
911
1087
|
// run through the x- and y-axes and update them by delta, within the original bounds
|
|
912
1088
|
panAxes(deltaX, xAxesForSeries, xAxesState, xRanges, setAxisRange, plotDimensions, margin, constrainToOriginalRange);
|
|
913
1089
|
panAxes(deltaY, yAxesForSeries, yAxesState, yRanges, setAxisRange, plotDimensions, margin, constrainToOriginalRange);
|
|
@@ -916,17 +1092,22 @@ export function panHandler2D(xAxesForSeries, yAxesForSeries, margin, setAxisRang
|
|
|
916
1092
|
}
|
|
917
1093
|
/**
|
|
918
1094
|
* Calculates the zoom for the specified axis and updates the axis and the axis ranges
|
|
919
|
-
* @param
|
|
920
|
-
*
|
|
1095
|
+
* @param pivotDomainValueFor Given the axis being zoomed, returns the domain value to pivot the
|
|
1096
|
+
* zoom around. Callers pass a function (rather than a fixed value) because the right pivot
|
|
1097
|
+
* depends on the axis's *own* domain/scale (e.g. inverting a shared mouse pixel position through
|
|
1098
|
+
* each axis's own scale, or reading each axis's own "now" tracking) -- there's no single value
|
|
1099
|
+
* that's correct for every axis when a plot has more than one (e.g. Scatter's dual x-axes).
|
|
1100
|
+
* @param axisId The id of the axis to zoom
|
|
921
1101
|
* @param margin The plot margin
|
|
922
|
-
* @param setRangeFor Function for setting the new time-range for a specific axis
|
|
923
|
-
* @param axesState
|
|
1102
|
+
* @param setRangeFor Function for setting the new time-range for a specific axis
|
|
1103
|
+
* @param axesState The current state of the x- or y-axes
|
|
924
1104
|
* @param ranges A map associating axis IDs with axis ranges
|
|
925
1105
|
* @param scaleExtent The smallest and largest scale factors allowed
|
|
926
|
-
* @param
|
|
1106
|
+
* @param zoomFactor The incremental zoom scale factor for this event -- see
|
|
1107
|
+
* {@link calculateConstrainedZoomFor} for what "incremental" means here
|
|
927
1108
|
* @param plotDimensions The dimensions of the plot
|
|
928
1109
|
*/
|
|
929
|
-
function calcZoomAndUpdate(
|
|
1110
|
+
function calcZoomAndUpdate(pivotDomainValueFor, axisId, margin, setRangeFor, axesState, ranges, scaleExtent, zoomFactor, plotDimensions) {
|
|
930
1111
|
const [, zoomMax] = scaleExtent;
|
|
931
1112
|
axesState.axisFor(axisId).ifPresent(axis => {
|
|
932
1113
|
const range = ranges.get(axisId);
|
|
@@ -935,7 +1116,7 @@ function calcZoomAndUpdate(value, axisId, margin, setRangeFor, axesState, ranges
|
|
|
935
1116
|
const constraint = isFinite(zoomMax) ?
|
|
936
1117
|
[range.original.start * zoomMax, range.original.end * zoomMax] :
|
|
937
1118
|
[0, Infinity];
|
|
938
|
-
const zoom = calculateConstrainedZoomFor(
|
|
1119
|
+
const zoom = calculateConstrainedZoomFor(zoomFactor, pivotDomainValueFor(axis), range, constraint);
|
|
939
1120
|
// update the axis range
|
|
940
1121
|
ranges.set(axisId, zoom.range);
|
|
941
1122
|
setRangeFor(axisId, zoom.range.current);
|
|
@@ -944,24 +1125,44 @@ function calcZoomAndUpdate(value, axisId, margin, setRangeFor, axesState, ranges
|
|
|
944
1125
|
}
|
|
945
1126
|
});
|
|
946
1127
|
}
|
|
947
|
-
|
|
1128
|
+
/**
|
|
1129
|
+
* Calculates the zoom for the specified ordinal axis and updates the axis and the axis ranges (the
|
|
1130
|
+
* original range is reset to the plot's width or height)
|
|
1131
|
+
* @param value The pixel position to pivot the zoom around (e.g. the mouse position)
|
|
1132
|
+
* @param axisId The id of the axis to zoom
|
|
1133
|
+
* @param margin The plot margin
|
|
1134
|
+
* @param setRangeFor Function for setting the new range for a specific axis
|
|
1135
|
+
* @param setOriginalRangeFor Function for setting the new original range for a specific axis
|
|
1136
|
+
* @param axesState The current state of the x- or y-axes
|
|
1137
|
+
* @param ranges A map associating axis IDs with axis ranges (updated with the zoomed range)
|
|
1138
|
+
* @param scaleExtent The smallest and largest scale factors allowed
|
|
1139
|
+
* @param zoomFactor The *cumulative* zoom scale factor for this event -- see
|
|
1140
|
+
* {@link calculateOrdinalConstrainedZoomFor}
|
|
1141
|
+
* @param plotDimensions The dimensions of the plot
|
|
1142
|
+
*/
|
|
1143
|
+
function calcOrdinalZoomAndUpdate(value, axisId, margin, setRangeFor, setOriginalRangeFor, axesState, ranges, scaleExtent, zoomFactor, plotDimensions) {
|
|
948
1144
|
const [, zoomMax] = scaleExtent;
|
|
949
1145
|
axesState.axisFor(axisId).ifPresent(axis => {
|
|
950
1146
|
const range = ranges.get(axisId);
|
|
951
1147
|
if (range && axis) {
|
|
952
1148
|
// calculate the constraint for the zoom
|
|
953
|
-
// const [originalStart, originalEnd] = range.original
|
|
954
1149
|
const constraint = isFinite(zoomMax) ?
|
|
955
1150
|
[range.original.start * zoomMax, range.original.end * zoomMax] :
|
|
956
1151
|
[range.original.start, range.original.end];
|
|
957
|
-
const zoom = calculateOrdinalConstrainedZoomFor(
|
|
1152
|
+
const zoom = calculateOrdinalConstrainedZoomFor(zoomFactor, value, range, constraint);
|
|
958
1153
|
// update the axis range
|
|
959
1154
|
ranges.set(axisId, zoom.range);
|
|
960
1155
|
setRangeFor(axisId, zoom.range.current);
|
|
961
|
-
|
|
1156
|
+
// the axis's pixel extent depends on its location: a top/bottom (x) axis spans the
|
|
1157
|
+
// plot's width, while a left/right (y) axis spans the plot's height
|
|
1158
|
+
const extent = axis.location === AxisLocation.Top || axis.location === AxisLocation.Bottom ?
|
|
1159
|
+
plotDimensions.width :
|
|
1160
|
+
plotDimensions.height;
|
|
1161
|
+
const origRange = AxisInterval.from(0, extent);
|
|
962
1162
|
setOriginalRangeFor(axisId, origRange);
|
|
963
|
-
// update the axis' range
|
|
964
|
-
axis
|
|
1163
|
+
// update the axis' range -- zooming never changes the set of categories, so pass the
|
|
1164
|
+
// axis's own current domain back unchanged
|
|
1165
|
+
axis.update(axis.scale.domain(), zoom.range.current, origRange, plotDimensions, margin);
|
|
965
1166
|
}
|
|
966
1167
|
});
|
|
967
1168
|
}
|
|
@@ -971,27 +1172,32 @@ function calcOrdinalZoomAndUpdate(value, axisId, margin, setRangeFor, setOrigina
|
|
|
971
1172
|
* function returns a handler function. And this handler function adjusts the range when the plot is zoomed.
|
|
972
1173
|
* After calling the handler function, the plot needs to be updated as well, and this is left for the caller.
|
|
973
1174
|
*
|
|
974
|
-
* Please note that the function generated by this function has side effects -- it updates the axes ranges.
|
|
1175
|
+
* Please note that the function generated by this function has side effects -- it updates the axes' ranges.
|
|
975
1176
|
*
|
|
976
1177
|
* @param axesForSeries The distinct axes that cover all the series
|
|
977
1178
|
* @param margin The plot margin
|
|
978
1179
|
* @param setRangeFor Function for setting the new time-range for a specific axis
|
|
979
1180
|
* @param axesState The current state of the x- or y-axes
|
|
980
|
-
* @param scaleExtent The minimum and maximum allowed scale factors
|
|
981
|
-
* @return A handler function for
|
|
1181
|
+
* @param [scaleExtent=[0, Infinity]] The minimum and maximum allowed scale factors
|
|
1182
|
+
* @return A handler function for zoom events
|
|
982
1183
|
*/
|
|
983
1184
|
export function continuousAxisZoomHandler(axesForSeries, margin, setRangeFor, axesState, scaleExtent = [0, Infinity]) {
|
|
984
1185
|
/**
|
|
985
|
-
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out.
|
|
986
|
-
*
|
|
987
|
-
*
|
|
988
|
-
*
|
|
1186
|
+
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out.
|
|
1187
|
+
* @param zoomFactor The *incremental* zoom scale factor for this event -- relative to each
|
|
1188
|
+
* axis's `.current`, not its `.original` (see {@link calculateConstrainedZoomFor}). Callers
|
|
1189
|
+
* must convert d3-zoom's cumulative `event.transform.k` to this incremental form themselves
|
|
1190
|
+
* (this event's `k` divided by the previously-applied `k`) before calling this handler.
|
|
1191
|
+
* @param pivotDomainValueFor Given an axis ID and its axis, returns the domain value to pivot
|
|
1192
|
+
* that axis's zoom around -- e.g. the mouse position inverted through that axis's own scale,
|
|
1193
|
+
* or (while streaming) that axis's own "now" tracking, so "now" stays fixed on screen as the
|
|
1194
|
+
* zoom widens/narrows the window around it instead of drifting with wherever the mouse is.
|
|
989
1195
|
* @param plotDimensions The dimensions of the plot
|
|
990
1196
|
* @param ranges A map holding the axis ID and its associated time-range
|
|
991
1197
|
*/
|
|
992
|
-
return (
|
|
1198
|
+
return (zoomFactor, pivotDomainValueFor, plotDimensions, ranges) => {
|
|
993
1199
|
// run through the axis IDs, adjust their domain, and update the time-range set for that axis
|
|
994
|
-
axesForSeries.forEach(axisId => calcZoomAndUpdate(
|
|
1200
|
+
axesForSeries.forEach(axisId => calcZoomAndUpdate(axis => pivotDomainValueFor(axisId, axis), axisId, margin, setRangeFor, axesState, ranges, scaleExtent, zoomFactor, plotDimensions));
|
|
995
1201
|
// hey, don't forget to update the plot with the new time-ranges in the code calling this... :)
|
|
996
1202
|
};
|
|
997
1203
|
}
|
|
@@ -1001,28 +1207,32 @@ export function continuousAxisZoomHandler(axesForSeries, margin, setRangeFor, ax
|
|
|
1001
1207
|
* function returns a handler function. And this handler function adjusts the range when the plot is zoomed.
|
|
1002
1208
|
* After calling the handler function, the plot needs to be updated as well, and this is left for the caller.
|
|
1003
1209
|
*
|
|
1004
|
-
* Please note that the function generated by this function has side effects -- it updates the axes ranges.
|
|
1210
|
+
* Please note that the function generated by this function has side effects -- it updates the axes' ranges.
|
|
1005
1211
|
*
|
|
1006
1212
|
* @param axesForSeries The distinct axes that cover all the series
|
|
1007
1213
|
* @param margin The plot margin
|
|
1008
1214
|
* @param setRangeFor Function for setting the new time-range for a specific axis
|
|
1009
1215
|
* @param setOriginalRangeFor Function for setting the new original range for a specific axis
|
|
1010
1216
|
* @param axesState The current state of the x- or y-axes
|
|
1011
|
-
* @param scaleExtent The minimum and maximum allowed scale factors
|
|
1012
|
-
* @return A handler function for
|
|
1217
|
+
* @param [scaleExtent=[0, Infinity]] The minimum and maximum allowed scale factors
|
|
1218
|
+
* @return A handler function for zoom events
|
|
1013
1219
|
*/
|
|
1014
1220
|
export function ordinalAxisZoomHandler(axesForSeries, margin, setRangeFor, setOriginalRangeFor, axesState, scaleExtent = [0, Infinity]) {
|
|
1015
1221
|
/**
|
|
1016
1222
|
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out. Zooms in/out
|
|
1017
1223
|
* at the location of the mouse when the scroll wheel or gesture was applied.
|
|
1018
|
-
* @param
|
|
1224
|
+
* @param zoomFactor The *cumulative* zoom scale factor for this event -- d3-zoom's own
|
|
1225
|
+
* `event.transform.k`, passed through unmodified. Unlike {@link continuousAxisZoomHandler},
|
|
1226
|
+
* this must NOT be converted to an incremental factor -- see
|
|
1227
|
+
* {@link OrdinalAxisRange.scaledCumulative} for why an ordinal axis's bounded domain needs
|
|
1228
|
+
* the raw cumulative factor instead.
|
|
1019
1229
|
* @param x The x-position of the mouse when the scroll wheel or gesture is used
|
|
1020
1230
|
* @param plotDimensions The dimensions of the plot
|
|
1021
1231
|
* @param ranges A map holding the axis ID and its associated time-range
|
|
1022
1232
|
*/
|
|
1023
|
-
return (
|
|
1233
|
+
return (zoomFactor, x, plotDimensions, ranges) => {
|
|
1024
1234
|
// run through the axis IDs, adjust their domain, and update the time-range set for that axis
|
|
1025
|
-
axesForSeries.forEach(axisId => calcOrdinalZoomAndUpdate(x, axisId, margin, setRangeFor, setOriginalRangeFor, axesState, ranges, scaleExtent,
|
|
1235
|
+
axesForSeries.forEach(axisId => calcOrdinalZoomAndUpdate(x, axisId, margin, setRangeFor, setOriginalRangeFor, axesState, ranges, scaleExtent, zoomFactor, plotDimensions));
|
|
1026
1236
|
// hey, don't forget to update the plot with the new time-ranges in the code calling this... :)
|
|
1027
1237
|
};
|
|
1028
1238
|
}
|
|
@@ -1032,7 +1242,7 @@ export function ordinalAxisZoomHandler(axesForSeries, margin, setRangeFor, setOr
|
|
|
1032
1242
|
* function returns a handler function. And this handler function adjusts the time-range when the plot is zoomed.
|
|
1033
1243
|
* After calling the handler function, the plot needs to be updated as well, and this is left for the caller.
|
|
1034
1244
|
*
|
|
1035
|
-
* Please note that the function generated by this function has side effects -- it updates the axes ranges.
|
|
1245
|
+
* Please note that the function generated by this function has side effects -- it updates the axes' ranges.
|
|
1036
1246
|
*
|
|
1037
1247
|
* @param xAxesForSeries The distinct x-axes that cover all the series
|
|
1038
1248
|
* @param yAxesForSeries The distinct y-axes that cover all the series
|
|
@@ -1041,46 +1251,50 @@ export function ordinalAxisZoomHandler(axesForSeries, margin, setRangeFor, setOr
|
|
|
1041
1251
|
* @param xAxesState The current state of the x-axes
|
|
1042
1252
|
* @param yAxesState The current state of the y-axes
|
|
1043
1253
|
* @param scaleExtent The smallest and largest scale factors allowed
|
|
1044
|
-
* @return A handler function for
|
|
1254
|
+
* @return A handler function for zoom events
|
|
1045
1255
|
*/
|
|
1046
1256
|
export function axesZoomHandler(xAxesForSeries, yAxesForSeries, margin, setRangeFor, xAxesState, yAxesState, scaleExtent) {
|
|
1047
1257
|
/**
|
|
1048
1258
|
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out. Zooms in/out
|
|
1049
1259
|
* at the location of the mouse when the scroll wheel or gesture was applied.
|
|
1050
|
-
* @param
|
|
1051
|
-
* @
|
|
1260
|
+
* @param zoomFactor The *incremental* zoom scale factor for this event -- see
|
|
1261
|
+
* {@link continuousAxisZoomHandler} for the full explanation of why this must already be
|
|
1262
|
+
* incremental (not d3-zoom's raw, cumulative `event.transform.k`)
|
|
1263
|
+
* @param mousePosition The position of the mouse when the scroll wheel or gesture is used
|
|
1052
1264
|
* @param plotDimensions The dimensions of the plot
|
|
1053
|
-
* @param
|
|
1265
|
+
* @param xRanges A map holding the x-axis ID and its associated time-range
|
|
1266
|
+
* @param yRanges A map holding the y-axis ID and its associated time-range
|
|
1054
1267
|
*/
|
|
1055
|
-
return (
|
|
1268
|
+
return (zoomFactor, mousePosition, plotDimensions, xRanges, yRanges) => {
|
|
1056
1269
|
// run through the axis IDs, adjust their domain, and update the time-range set for that axis
|
|
1057
1270
|
const [x, y] = mousePosition;
|
|
1058
|
-
xAxesForSeries.forEach(id => calcZoomAndUpdate(x, id, margin, setRangeFor, xAxesState, xRanges, scaleExtent,
|
|
1059
|
-
yAxesForSeries.forEach(id => calcZoomAndUpdate(y, id, margin, setRangeFor, yAxesState, yRanges, scaleExtent,
|
|
1271
|
+
xAxesForSeries.forEach(id => calcZoomAndUpdate(axis => axis.scale.invert(x), id, margin, setRangeFor, xAxesState, xRanges, scaleExtent, zoomFactor, plotDimensions));
|
|
1272
|
+
yAxesForSeries.forEach(id => calcZoomAndUpdate(axis => axis.scale.invert(y), id, margin, setRangeFor, yAxesState, yRanges, scaleExtent, zoomFactor, plotDimensions));
|
|
1060
1273
|
// hey, don't forget to update the plot with the new time-ranges in the code calling this... :)
|
|
1061
1274
|
};
|
|
1062
1275
|
}
|
|
1063
1276
|
/**
|
|
1064
|
-
* Calculates the axis-ranges for each of the continuous numeric axes in the map
|
|
1277
|
+
* Calculates the axis-ranges for each of the continuous numeric axes in the map, from each axis'
|
|
1278
|
+
* current domain (see {@link continuousRange})
|
|
1065
1279
|
* @param axes The map containing the axes and their associated IDs
|
|
1066
|
-
* @return a map associating the axis IDs
|
|
1280
|
+
* @return a map associating the axis IDs with their continuous axis-range
|
|
1067
1281
|
*/
|
|
1068
1282
|
export function continuousAxisRanges(axes) {
|
|
1069
1283
|
return continuousRange(axes);
|
|
1070
1284
|
}
|
|
1071
1285
|
/**
|
|
1072
|
-
* Calculates the axis-ranges for each of the ordinal axes in the map
|
|
1286
|
+
* Calculates the axis-ranges for each of the ordinal axes in the map, read from each axis's own
|
|
1287
|
+
* scale range.
|
|
1073
1288
|
* @param axes The map containing the axes and their associated IDs
|
|
1074
|
-
* @
|
|
1075
|
-
* @return a map associating the axis IDs to their ordinal axis-range
|
|
1289
|
+
* @return a map associating the axis IDs with their ordinal axis-range
|
|
1076
1290
|
*/
|
|
1077
|
-
export function ordinalAxisRanges(axes
|
|
1078
|
-
return ordinalRange(axes
|
|
1291
|
+
export function ordinalAxisRanges(axes) {
|
|
1292
|
+
return ordinalRange(axes);
|
|
1079
1293
|
}
|
|
1080
1294
|
/**
|
|
1081
|
-
* Calculates the axis interval (start, end)
|
|
1082
|
-
* @param axes The axes
|
|
1083
|
-
* @return A map associating each axis with
|
|
1295
|
+
* Calculates the axis interval (start, end) of each axis' current domain
|
|
1296
|
+
* @param axes The axes, by their IDs
|
|
1297
|
+
* @return A map associating each axis ID with its domain's (start, end) interval
|
|
1084
1298
|
*/
|
|
1085
1299
|
export function continuousAxisIntervals(axes) {
|
|
1086
1300
|
return new Map(Array.from(axes.entries())
|
|
@@ -1090,9 +1304,10 @@ export function continuousAxisIntervals(axes) {
|
|
|
1090
1304
|
}));
|
|
1091
1305
|
}
|
|
1092
1306
|
/**
|
|
1093
|
-
* Calculates the
|
|
1094
|
-
*
|
|
1095
|
-
* @
|
|
1307
|
+
* Calculates the pixel interval (start, end) of each ordinal axis' current range, along with its
|
|
1308
|
+
* categories
|
|
1309
|
+
* @param axes The axes, by their IDs
|
|
1310
|
+
* @return A map associating each axis ID with its range's (start, end) interval and its categories
|
|
1096
1311
|
*/
|
|
1097
1312
|
export function ordinalAxisIntervals(axes) {
|
|
1098
1313
|
return new Map(Array.from(axes.entries())
|
|
@@ -1102,7 +1317,8 @@ export function ordinalAxisIntervals(axes) {
|
|
|
1102
1317
|
}));
|
|
1103
1318
|
}
|
|
1104
1319
|
/**
|
|
1105
|
-
* Returns the bounds on the specified continuous numeric axes
|
|
1320
|
+
* Returns the bounds on the specified continuous numeric axes: a new axis range (with its original
|
|
1321
|
+
* range the same as its current range) from each axis' current domain
|
|
1106
1322
|
* @param axes A map associating an axis ID with a {@link ContinuousNumericAxis}
|
|
1107
1323
|
* @return A map associating each specified axis ID with the interval covered (bounds) by the axis
|
|
1108
1324
|
*/
|
|
@@ -1114,13 +1330,22 @@ export function continuousRange(axes) {
|
|
|
1114
1330
|
}));
|
|
1115
1331
|
}
|
|
1116
1332
|
/**
|
|
1117
|
-
* Returns the bounds on the specified
|
|
1333
|
+
* Returns the bounds on the specified ordinal axes, read from each axis's own scale range.
|
|
1334
|
+
*
|
|
1335
|
+
* Previously mapped every axis ID to one shared, caller-supplied `originalRange`, discarding the
|
|
1336
|
+
* axis object entirely (`[id, ]`) -- harmless today only because there's no per-axis margin/offset
|
|
1337
|
+
* mechanism anywhere in this codebase, so every ordinal axis in a chart is architecturally
|
|
1338
|
+
* guaranteed to span the same pixel range already. Reading each axis's own `.scale.range()`
|
|
1339
|
+
* instead (mirroring {@link ordinalAxisIntervals}, which already does this correctly) removes that
|
|
1340
|
+
* latent footgun for a chart with multiple category axes whose ranges genuinely differ.
|
|
1118
1341
|
* @param axes A map associating an axis ID with a {@link OrdinalStringAxis}
|
|
1119
|
-
* @param originalRange The original range of the axis
|
|
1120
1342
|
* @return A map associating each specified axis ID with the interval covered (bounds) by the axis
|
|
1121
1343
|
*/
|
|
1122
|
-
export function ordinalRange(axes
|
|
1344
|
+
export function ordinalRange(axes) {
|
|
1123
1345
|
return new Map(Array.from(axes.entries())
|
|
1124
|
-
.map(([id,
|
|
1346
|
+
.map(([id, axis]) => {
|
|
1347
|
+
const [start, end] = axis.scale.range();
|
|
1348
|
+
return [id, OrdinalAxisRange.from(start, end)];
|
|
1349
|
+
}));
|
|
1125
1350
|
}
|
|
1126
1351
|
//# sourceMappingURL=axes.js.map
|