Skip to content

Commit

Permalink
🎉 added alternating stroke color to distinguish values above threshol…
Browse files Browse the repository at this point in the history
…d and below threshold
  • Loading branch information
kunkoala committed Dec 10, 2024
1 parent 92c18e3 commit 5304930
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 38 deletions.
2 changes: 1 addition & 1 deletion frontend/src/DataContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ export const DataProvider = ({children}: {children: React.ReactNode}) => {
visible: true,
fill: color(getScenarioPrimaryColor(selectedScenario, theme)),
fillOpacity: 0.3,
stroke: {strokeWidth: 0},
stroke: {strokeWidth: 0, visible: false},
parentId: selectedScenario,
};
}
Expand Down
60 changes: 39 additions & 21 deletions frontend/src/components/LineChartComponents/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,29 +364,43 @@ export default function LineChart({
});
}, [lineChartData, root, xAxis, yAxis, chartId]);

// Effect to add series range above threshold to chart
// this sets the chart settings above the threshold
const seriesRangeSettings = useMemo(() => {
if (!root || !horizontalYAxisThreshold || horizontalYAxisThreshold === 0) {
return {};
if (!root || !horizontalYAxisThreshold || horizontalYAxisThreshold === 0 || !lineChartData) {
return [];
}

return {
threshold: horizontalYAxisThreshold,
fills: {
fill: color(theme.palette.error.main),
fillOpacity: 0.3,
visible: true,
},
strokes: {
stroke: color(theme.palette.error.main),
strokeWidth: 2,
strokeOpacity: 1,
strokeDasharray: [6, 4],
visible: true,
},
};
}, [root, horizontalYAxisThreshold, theme.palette.error.main]);
return lineChartData.map((line) => {
const lineColor = line.stroke.color ?? color(theme.palette.error.main);
const fillColor = line.fill ?? color(theme.palette.error.main);

return {
serieId: line.serieId ?? '',
threshold: horizontalYAxisThreshold,
fills: {
fill: fillColor, // change the fill of the range above threshold
visible: true, // visibility of the fill
fillOpacity: line.fillOpacity ?? 0.15,
},
strokes: {
stroke: color(theme.palette.error.main), // change the stroke for points above threshold
strokeWidth: line.stroke.strokeWidth ?? 2,
strokeOpacity: 1,
visible: line.stroke.visible ?? true, // use the one from the lineChartData if it is defined
},
alternatingStrokes: {
stroke: lineColor,
strokeWidth: 2,
layer: 1,
strokeDasharray: [10, 10],
strokeOpacity: 1,
visible: line.stroke.visible ?? true,
},
};
});
}, [root, horizontalYAxisThreshold, theme.palette.error.main, lineChartData]);

// add linechart and series. The lineSeries will be initialized using the initializer, whereas the seriesRange will be initialized using the seriesRangeSettings
useSeriesRange(
root,
chart,
Expand All @@ -398,13 +412,17 @@ export default function LineChart({
if (!lineChartData) return;

const seriesSettings = lineChartData.find((line) => line.serieId === series.get('id')?.split('_')[1]);
console.log(seriesSettings);

// set stroke settings from original line chart data below the threshold
series.strokes.template.setAll({
strokeWidth: seriesSettings?.stroke.strokeWidth ?? 2,
strokeDasharray: seriesSettings?.stroke.strokeDasharray ?? undefined,
});

// set fill settings from original line chart data below the threshold
if (seriesSettings?.fill) {
series.fills.template.setAll({
fill: seriesSettings.fill,
fillOpacity: seriesSettings.fillOpacity ?? 1,
visible: true,
});
Expand All @@ -429,7 +447,7 @@ export default function LineChart({
grid: {
stroke: color(theme.palette.error.main), // Use dynamic stroke color based on the threshold
strokeOpacity: 0.8,
strokeWidth: 1.5,
strokeWidth: 2,
visible: true,
location: 0,
},
Expand Down
43 changes: 27 additions & 16 deletions frontend/src/components/shared/LineChart/SeriesRange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,48 @@ export function useSeriesRange(
root: Root | null,
chart: XYChart | null,
settings: Array<ILineSeriesSettings>,
yAxis: ValueAxis<AxisRenderer> | null, // The yAxis for creating range
rangeSettings: {
threshold?: number; // The threshold for the series range
fills?: Partial<IGraphicsSettings>; // Fill color for the range
strokes?: Partial<IGraphicsSettings>; // Stroke color for the range
},
yAxis: ValueAxis<AxisRenderer> | null,
rangeSettings: Array<{
serieId?: string | number;
threshold?: number;
fills?: Partial<IGraphicsSettings>;
strokes?: Partial<IGraphicsSettings>;
alternatingStrokes?: Partial<IGraphicsSettings>;
}>, // Update to accept an array of settings
initializer?: (series: LineSeries, i: number) => void
) {
// Use the existing `useLineSeriesList` hook to create the series
const seriesList = useLineSeriesList(root, chart, settings, initializer);

// Use `useLayoutEffect` to apply the series range logic after the series are created
useLayoutEffect(() => {
if (!seriesList || !yAxis || seriesList.length === 0) return;
if (!seriesList || !yAxis || seriesList.length === 0 || !rangeSettings) return;

// Iterate over each series passed on and match the corresponding range settings
seriesList.forEach((series: LineSeries, index: number) => {
const rangeSetting = rangeSettings[index]; // Match range settings by index
if (!rangeSetting || !rangeSetting.threshold) return;

// Iterate over each series to create and apply the series range
seriesList.forEach((series: LineSeries) => {
const seriesRangeDataItem = yAxis.makeDataItem({
value: rangeSettings.threshold, // Start of the range
value: rangeSetting.threshold, // Start of the range
endValue: 1e6, // End value of the range (adjust as needed)
});

const seriesRange = series.createAxisRange(seriesRangeDataItem);
const aboveThresholdRange = series.createAxisRange(seriesRangeDataItem);

// Apply the fill settings
if (rangeSetting.fills) {
aboveThresholdRange.fills?.template.setAll(rangeSetting.fills);
}

// Set the fill and stroke properties for the range
if (rangeSettings.fills) {
seriesRange.fills?.template.setAll(rangeSettings.fills);
// Apply the stroke settings
if (rangeSetting.strokes) {
aboveThresholdRange.strokes?.template.setAll(rangeSetting.strokes);
}

if (rangeSettings.strokes) {
seriesRange.strokes?.template.setAll(rangeSettings.strokes);
if (rangeSetting.alternatingStrokes) {
const alternatingStrokeSeriesRange = series.createAxisRange(seriesRangeDataItem);
alternatingStrokeSeriesRange.strokes?.template.setAll(rangeSetting.alternatingStrokes);
}
});

Expand Down
10 changes: 10 additions & 0 deletions frontend/src/types/lineChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ export interface LineChartData {
* The dash array for the stroke.
*/
strokeDasharray?: number[];

/**
* The opacity of the stroke.
*/
strokeOpacity?: number;

/**
* visibility of the stroke
*/
visible?: boolean;
};

/**
Expand Down

0 comments on commit 5304930

Please sign in to comment.