Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable 'tozeroy' mode for Area Charts #33581

Merged
merged 13 commits into from
Jan 17, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
srmukher marked this conversation as resolved.
Show resolved Hide resolved
srmukher marked this conversation as resolved.
Show resolved Hide resolved
srmukher marked this conversation as resolved.
Show resolved Hide resolved
srmukher marked this conversation as resolved.
Show resolved Hide resolved
"type": "patch",
"comment": "Support tozeroy mode for Area Charts",
"packageName": "@fluentui/react-charting",
"email": "[email protected]",
"dependentChangeType": "patch"
}
1 change: 1 addition & 0 deletions packages/charts/react-charting/etc/react-charting.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export interface IAreaChartProps extends ICartesianChartProps {
data: IChartProps;
enableGradient?: boolean;
enablePerfOptimization?: boolean;
mode?: string;
onRenderCalloutPerDataPoint?: IRenderFunction<ICustomizedCalloutData>;
onRenderCalloutPerStack?: IRenderFunction<ICustomizedCalloutData>;
// (undocumented)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
import { ILegend, Legends } from '../Legends/index';
import { DirectionalHint } from '@fluentui/react/lib/Callout';
import { IChart } from '../../types/index';
import { AreaChartModes } from './AreaChart.types';

const getClassNames = classNamesFunction<IAreaChartStyleProps, IAreaChartStyles>();

Expand All @@ -64,7 +65,7 @@ export interface IAreaChartAreaPoint {
values: IAreaChartDataSetPoint;
}
export interface IAreaChartDataSetPoint {
[key: string]: number | string;
[key: string]: number | string | number[];
}
export interface IDPointType {
values: { 0: number; 1: number; data: {} };
Expand Down Expand Up @@ -457,6 +458,30 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
};
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _getStackedDataZeroToY = (keys: string[], dataSet: any) => {
srmukher marked this conversation as resolved.
Show resolved Hide resolved
const stackedValues = d3Stack().keys(keys)(dataSet);
const maxOfYVal = d3Max(stackedValues[stackedValues.length - 1], dp => dp[1])!;
const stackedData: Array<IAreaChartDataSetPoint[]> = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
stackedValues.forEach((layer: any, layerIndex: number) => {
const currentStack: IAreaChartDataSetPoint[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.forEach((d: any, index: number) => {
currentStack.push({
values: [0, d[1]],
xVal: d.data.xVal,
});
});
stackedData.push(currentStack);
});
this._isMultiStackChart = stackedData && stackedData.length > 1 ? true : false;
return {
srmukher marked this conversation as resolved.
Show resolved Hide resolved
stackedData,
maxOfYVal,
};
};

private _createDataSet = (points: ILineChartPoints[]) => {
if (this.props.enablePerfOptimization && this._enableComputationOptimization) {
const allChartPoints: ILineChartDataPoint[] = [];
Expand Down Expand Up @@ -505,7 +530,10 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
}

// Stacked Info used to draw graph
const stackedInfo = this._getStackedData(keys, dataSet);
const stackedInfo =
this.props.mode === AreaChartModes.toZeroY
? this._getStackedDataZeroToY(keys, dataSet)
: this._getStackedData(keys, dataSet);

return {
colors,
Expand Down Expand Up @@ -558,7 +586,10 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
}

// Stacked Info used to draw graph
const stackedInfo = this._getStackedData(keys, dataSet);
const stackedInfo =
srmukher marked this conversation as resolved.
Show resolved Hide resolved
this.props.mode === AreaChartModes.toZeroY
? this._getStackedDataZeroToY(keys, dataSet)
: this._getStackedData(keys, dataSet);

return {
colors,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ import {

export type { IChildProps, IRefArrayData, IBasestate, ILineChartDataPoint, ILineChartPoints, IMargins };

/**
* Area Chart modes
* {@docCategory AreaChart}
*/
export enum AreaChartModes {
/**
* This mode will fill the area from the line to the x-axis.
*/
toZeroY = 'tozeroy',

/**
* This mode will fill the area from the line to the next line.
*/
toNextY = 'tonexty',
}

/**
* Area Chart properties.
* {@docCategory AreaChart}
Expand Down Expand Up @@ -70,6 +86,11 @@ export interface IAreaChartProps extends ICartesianChartProps {
* The prop used to enable gradient fill color for the chart.
*/
enableGradient?: boolean;

/**
* The prop used to define the Y axis mode (tonexty or tozeroy)
srmukher marked this conversation as resolved.
Show resolved Hide resolved
*/
mode?: string;
srmukher marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { ISankeyChartProps } from '../SankeyChart/index';
import { IVerticalStackedBarChartProps } from '../VerticalStackedBarChart/index';
import { IHorizontalBarChartWithAxisProps } from '../HorizontalBarChartWithAxis/index';
import { ILineChartProps } from '../LineChart/index';
import { IAreaChartProps } from '../AreaChart/index';
import { AreaChartModes, IAreaChartProps } from '../AreaChart/index';
import { IHeatMapChartProps } from '../HeatMapChart/index';
import { DataVizPalette, getNextColor } from '../../utilities/colors';
import { GaugeChartVariant, IGaugeChartProps, IGaugeChartSegment } from '../GaugeChart/index';
Expand Down Expand Up @@ -339,6 +339,7 @@ export const transformPlotlyJsonToScatterChartProps = (
isDarkTheme?: boolean,
): ILineChartProps | IAreaChartProps => {
const { data, layout } = jsonObj;
let mode: AreaChartModes = AreaChartModes.toNextY;

const chartData: ILineChartPoints[] = data.map((series: any, index: number) => {
const xValues = series.x;
Expand All @@ -347,6 +348,7 @@ export const transformPlotlyJsonToScatterChartProps = (
const isXNumber = isNumberArray(xValues);
const legend: string = series.name || `Series ${index + 1}`;
const lineColor = getColor(legend, colorMap, isDarkTheme);
mode = series.fill === 'tozeroy' ? AreaChartModes.toZeroY : AreaChartModes.toNextY;

return {
legend,
Expand All @@ -371,6 +373,7 @@ export const transformPlotlyJsonToScatterChartProps = (
supportNegativeData: true,
xAxisTitle,
yAxisTitle,
mode,
} as IAreaChartProps;
} else {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface IAreaChartBasicState {
isCalloutselected: boolean;
showAxisTitles: boolean;
legendMultiSelect: boolean;
changeChartMode: boolean;
}

const options: IChoiceGroupOption[] = [
Expand All @@ -26,6 +27,7 @@ export class AreaChartBasicExample extends React.Component<{}, IAreaChartBasicSt
isCalloutselected: false,
showAxisTitles: true,
legendMultiSelect: false,
changeChartMode: false,
};
}
public componentDidMount(): void {
Expand Down Expand Up @@ -75,6 +77,11 @@ export class AreaChartBasicExample extends React.Component<{}, IAreaChartBasicSt
this.setState({ legendMultiSelect: checked });
};

private _onToggleChartMode = (ev: React.MouseEvent<HTMLElement>, checked: boolean) => {
this.forceUpdate();
this.setState({ changeChartMode: checked });
};

private _basicExample(): JSX.Element {
const chart1Points = [
{
Expand Down Expand Up @@ -249,6 +256,14 @@ export class AreaChartBasicExample extends React.Component<{}, IAreaChartBasicSt
onChange={this._onToggleLegendMultiSelect}
styles={{ root: { marginTop: '10px' } }}
/>
<Toggle
label="Change chart mode to toZeroY"
onText="ON"
offText="OFF"
checked={this.state.changeChartMode}
onChange={this._onToggleChartMode}
styles={{ root: { marginTop: '10px' } }}
/>
{this.state.showAxisTitles && (
<div style={rootStyle}>
<AreaChart
Expand All @@ -274,6 +289,7 @@ export class AreaChartBasicExample extends React.Component<{}, IAreaChartBasicSt
legendProps={{
canSelectMultipleLegends: this.state.legendMultiSelect,
}}
mode={this.state.changeChartMode ? 'tozeroy' : 'tonexty'}
/>
</div>
)}
Expand All @@ -300,6 +316,7 @@ export class AreaChartBasicExample extends React.Component<{}, IAreaChartBasicSt
legendProps={{
canSelectMultipleLegends: this.state.legendMultiSelect,
}}
mode={this.state.changeChartMode ? 'tozeroy' : 'tonexty'}
/>
</div>
)}
Expand Down
Loading