From 070f9e38481362e1ad55f036915deb66d8a16648 Mon Sep 17 00:00:00 2001 From: Eric Yang <59426533+hlyang397@users.noreply.github.com> Date: Fri, 9 Oct 2020 00:11:02 +0800 Subject: [PATCH] feat: provide option to refresh range axis label (#766) * feat: provide option to refresh range axis label - add refreshRangeAxisLabel option (default to false) - add filterDataForRangeAxisLabel() in zoom service to provide data in zoom domain * refactor: move updateRangeAxis to zoomBarsOptions * refactor: use configs object instead of boolean as parameter * refactor: move updateWhenZooming option to be under axis option * refactor: change updateWhenZooming option to zoomBar.updateRangeAxis --- packages/core/src/configuration.ts | 3 +- packages/core/src/interfaces/components.ts | 4 ++ .../core/src/services/scales-cartesian.ts | 10 ++- packages/core/src/services/zoom.ts | 69 ++++++++++++++++++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/packages/core/src/configuration.ts b/packages/core/src/configuration.ts index 12e272462c..e5649ac4b1 100644 --- a/packages/core/src/configuration.ts +++ b/packages/core/src/configuration.ts @@ -173,7 +173,8 @@ const axisChart: AxisChartOptions = Tools.merge({}, chart, { top: { enabled: false, type: ZoomBarTypes.GRAPH_VIEW - } + }, + updateRangeAxis: false } as ZoomBarsOptions } as AxisChartOptions); diff --git a/packages/core/src/interfaces/components.ts b/packages/core/src/interfaces/components.ts index 63bf0b4941..9f56e48c5d 100644 --- a/packages/core/src/interfaces/components.ts +++ b/packages/core/src/interfaces/components.ts @@ -135,6 +135,10 @@ export interface ZoomBarsOptions { * currently only the top position is supported */ top?: ZoomBarOptions; + /** + * whether keep updating range axis in real time while zoom domain is changing + */ + updateRangeAxis?: boolean; } /** diff --git a/packages/core/src/services/scales-cartesian.ts b/packages/core/src/services/scales-cartesian.ts index 80c0681a67..ae233eac18 100644 --- a/packages/core/src/services/scales-cartesian.ts +++ b/packages/core/src/services/scales-cartesian.ts @@ -416,14 +416,20 @@ export class CartesianScales extends Service { let allDataValues; // If the scale is stacked if (axisOptions.stacked) { - const dataValuesGroupedByKeys = this.model.getDataValuesGroupedByKeys(); + const dataValuesGroupedByKeys = this.services.zoom.filterDataForRangeAxis( + this.model.getDataValuesGroupedByKeys(), + { stacked: true } + ); + allDataValues = dataValuesGroupedByKeys.map((dataValues) => sum(values(dataValues) as any) ); } else if (scaleType === ScaleTypes.TIME) { allDataValues = displayData.map((datum) => +new Date(datum[mapsTo])); } else { - allDataValues = displayData.map((datum) => datum[mapsTo]); + allDataValues = this.services.zoom + .filterDataForRangeAxis(displayData) + .map((datum) => datum[mapsTo]); } if (scaleType !== ScaleTypes.TIME && includeZero) { diff --git a/packages/core/src/services/zoom.ts b/packages/core/src/services/zoom.ts index 393e957ac4..c02311ef6f 100644 --- a/packages/core/src/services/zoom.ts +++ b/packages/core/src/services/zoom.ts @@ -1,12 +1,47 @@ // Internal Imports +import { AxisPositions, Events, ScaleTypes } from "../interfaces"; import { Service } from "./service"; -import { Events } from "../interfaces"; import { Tools } from "../tools"; // D3 imports import { extent } from "d3-array"; export class Zoom extends Service { + isZoomBarEnabled() { + // CartesianScales service is only available in axis charts + if (!this.services.cartesianScales) { + return false; + } + + // @todo - need to update this if zoom bar in other position (bottom, left, right) is supported + // check configuration + if ( + !Tools.getProperty( + this.model.getOptions(), + "zoomBar", + "top", + "enabled" + ) + ) { + return false; + } + + // @todo - Zoom Bar only supports main axis at BOTTOM axis and time scale for now + this.services.cartesianScales.findDomainAndRangeAxes(); // need to do this before getMainXAxisPosition() + const mainXAxisPosition = this.services.cartesianScales.getMainXAxisPosition(); + const mainXScaleType = Tools.getProperty( + this.model.getOptions(), + "axes", + mainXAxisPosition, + "scaleType" + ); + + return ( + mainXAxisPosition === AxisPositions.BOTTOM && + mainXScaleType === ScaleTypes.TIME + ); + } + // get display data for zoom bar // basically it's sum of value grouped by time getZoomBarData() { @@ -85,4 +120,36 @@ export class Zoom extends Service { "zoomRatio" ); } + + // filter out data not inside zoom domain + // to get better range value for axis label + filterDataForRangeAxis(displayData: object[], configs?: any) { + const zoomDomain = this.model.get("zoomDomain"); + const mergedConfigs = Object.assign( + { stacked: false }, // default configs + configs + ); + const shouldUpdateRangeAxis = Tools.getProperty( + this.model.getOptions(), + "zoomBar", + "updateRangeAxis" + ); + if (this.isZoomBarEnabled() && shouldUpdateRangeAxis && zoomDomain) { + const domainIdentifier = mergedConfigs.stacked + ? "sharedStackKey" + : this.services.cartesianScales.getDomainIdentifier(); + const filteredData = displayData.filter( + (datum) => + new Date(datum[domainIdentifier]) >= zoomDomain[0] && + new Date(datum[domainIdentifier]) <= zoomDomain[1] + ); + // if no data in zoom domain, use all data to get full range value + // so only return filteredData if length > 0 + if (filteredData.length > 0) { + return filteredData; + } + } + // return original data by default + return displayData; + } }