Browse Source

Feature/improve font color assignment in tree map chart component (#3954)

* Improve font color assignment in tree map chart component

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
pull/3976/head
Veer Chaurasia 3 months ago
committed by GitHub
parent
commit
e25aebf26f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 5
      libs/ui/src/lib/treemap-chart/interfaces/interfaces.ts
  3. 177
      libs/ui/src/lib/treemap-chart/treemap-chart.component.ts

1
CHANGELOG.md

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Improved the font colors of the chart of the holdings tab on the home page (experimental)
- Optimized the dialog sizes for mobile (full screen) - Optimized the dialog sizes for mobile (full screen)
- Upgraded `angular` from version `18.1.1` to `18.2.8` - Upgraded `angular` from version `18.1.1` to `18.2.8`
- Upgraded `Nx` from version `19.5.6` to `20.0.3` - Upgraded `Nx` from version `19.5.6` to `20.0.3`

5
libs/ui/src/lib/treemap-chart/interfaces/interfaces.ts

@ -0,0 +1,5 @@
export interface GetColorParams {
annualizedNetPerformancePercent: number;
negativeNetPerformancePercentsRange: { max: number; min: number };
positiveNetPerformancePercentsRange: { max: number; min: number };
}

177
libs/ui/src/lib/treemap-chart/treemap-chart.component.ts

@ -33,6 +33,8 @@ import { differenceInDays, max } from 'date-fns';
import { orderBy } from 'lodash'; import { orderBy } from 'lodash';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GetColorParams } from './interfaces/interfaces';
const { gray, green, red } = require('open-color'); const { gray, green, red } = require('open-color');
@Component({ @Component({
@ -63,7 +65,6 @@ export class GfTreemapChartComponent
public constructor() { public constructor() {
Chart.register(LinearScale, Tooltip, TreemapController, TreemapElement); Chart.register(LinearScale, Tooltip, TreemapController, TreemapElement);
} }
public ngAfterViewInit() { public ngAfterViewInit() {
if (this.holdings) { if (this.holdings) {
this.initialize(); this.initialize();
@ -80,6 +81,79 @@ export class GfTreemapChartComponent
this.chart?.destroy(); this.chart?.destroy();
} }
private getColor({
annualizedNetPerformancePercent,
negativeNetPerformancePercentsRange,
positiveNetPerformancePercentsRange
}: GetColorParams) {
if (Math.abs(annualizedNetPerformancePercent) === 0) {
return {
backgroundColor: gray[3],
fontColor: gray[9]
};
}
if (annualizedNetPerformancePercent > 0) {
let backgroundIndex: number;
const range =
positiveNetPerformancePercentsRange.max -
positiveNetPerformancePercentsRange.min;
if (
annualizedNetPerformancePercent >=
positiveNetPerformancePercentsRange.max - range * 0.25
) {
backgroundIndex = 9;
} else if (
annualizedNetPerformancePercent >=
positiveNetPerformancePercentsRange.max - range * 0.5
) {
backgroundIndex = 7;
} else if (
annualizedNetPerformancePercent >=
positiveNetPerformancePercentsRange.max - range * 0.75
) {
backgroundIndex = 5;
} else {
backgroundIndex = 3;
}
return {
backgroundColor: green[backgroundIndex],
fontColor: green[backgroundIndex <= 4 ? 9 : 0]
};
} else {
let backgroundIndex: number;
const range =
negativeNetPerformancePercentsRange.min -
negativeNetPerformancePercentsRange.max;
if (
annualizedNetPerformancePercent <=
negativeNetPerformancePercentsRange.min + range * 0.25
) {
backgroundIndex = 9;
} else if (
annualizedNetPerformancePercent <=
negativeNetPerformancePercentsRange.min + range * 0.5
) {
backgroundIndex = 7;
} else if (
annualizedNetPerformancePercent <=
negativeNetPerformancePercentsRange.min + range * 0.75
) {
backgroundIndex = 5;
} else {
backgroundIndex = 3;
}
return {
backgroundColor: red[backgroundIndex],
fontColor: red[backgroundIndex <= 4 ? 9 : 0]
};
}
}
private initialize() { private initialize() {
this.isLoading = true; this.isLoading = true;
@ -126,8 +200,8 @@ export class GfTreemapChartComponent
const data: ChartConfiguration['data'] = { const data: ChartConfiguration['data'] = {
datasets: [ datasets: [
{ {
backgroundColor(ctx) { backgroundColor: (ctx) => {
let annualizedNetPerformancePercentWithCurrencyEffect = let annualizedNetPerformancePercent =
getAnnualizedPerformancePercent({ getAnnualizedPerformancePercent({
daysInMarket: differenceInDays( daysInMarket: differenceInDays(
endDate, endDate,
@ -142,74 +216,51 @@ export class GfTreemapChartComponent
}).toNumber(); }).toNumber();
// Round to 2 decimal places // Round to 2 decimal places
annualizedNetPerformancePercentWithCurrencyEffect = annualizedNetPerformancePercent =
Math.round( Math.round(annualizedNetPerformancePercent * 100) / 100;
annualizedNetPerformancePercentWithCurrencyEffect * 100
) / 100;
if (
Math.abs(annualizedNetPerformancePercentWithCurrencyEffect) === 0
) {
annualizedNetPerformancePercentWithCurrencyEffect = Math.abs(
annualizedNetPerformancePercentWithCurrencyEffect
);
return gray[3];
} else if (annualizedNetPerformancePercentWithCurrencyEffect > 0) {
const range =
positiveNetPerformancePercentsRange.max -
positiveNetPerformancePercentsRange.min;
if (
annualizedNetPerformancePercentWithCurrencyEffect >=
positiveNetPerformancePercentsRange.max - range * 0.25
) {
return green[9];
} else if (
annualizedNetPerformancePercentWithCurrencyEffect >=
positiveNetPerformancePercentsRange.max - range * 0.5
) {
return green[7];
} else if (
annualizedNetPerformancePercentWithCurrencyEffect >=
positiveNetPerformancePercentsRange.max - range * 0.75
) {
return green[5];
}
return green[3]; const { backgroundColor } = this.getColor({
} else { annualizedNetPerformancePercent,
const range = negativeNetPerformancePercentsRange,
negativeNetPerformancePercentsRange.min - positiveNetPerformancePercentsRange
negativeNetPerformancePercentsRange.max; });
if (
annualizedNetPerformancePercentWithCurrencyEffect <=
negativeNetPerformancePercentsRange.min + range * 0.25
) {
return red[9];
} else if (
annualizedNetPerformancePercentWithCurrencyEffect <=
negativeNetPerformancePercentsRange.min + range * 0.5
) {
return red[7];
} else if (
annualizedNetPerformancePercentWithCurrencyEffect <=
negativeNetPerformancePercentsRange.min + range * 0.75
) {
return red[5];
}
return red[3]; return backgroundColor;
}
}, },
borderRadius: 4, borderRadius: 4,
key: 'allocationInPercentage', key: 'allocationInPercentage',
labels: { labels: {
align: 'left', align: 'left',
color: ['white'], color: (ctx) => {
let annualizedNetPerformancePercent =
getAnnualizedPerformancePercent({
daysInMarket: differenceInDays(
endDate,
max([
ctx.raw._data.dateOfFirstActivity ?? new Date(0),
startDate
])
),
netPerformancePercentage: new Big(
ctx.raw._data.netPerformancePercentWithCurrencyEffect
)
}).toNumber();
// Round to 2 decimal places
annualizedNetPerformancePercent =
Math.round(annualizedNetPerformancePercent * 100) / 100;
const { fontColor } = this.getColor({
annualizedNetPerformancePercent,
negativeNetPerformancePercentsRange,
positiveNetPerformancePercentsRange
});
return fontColor;
},
display: true, display: true,
font: [{ size: 16 }, { lineHeight: 1.5, size: 14 }], font: [{ size: 16 }, { lineHeight: 1.5, size: 14 }],
formatter(ctx) { formatter: (ctx) => {
const netPerformancePercentWithCurrencyEffect = const netPerformancePercentWithCurrencyEffect =
ctx.raw._data.netPerformancePercentWithCurrencyEffect; ctx.raw._data.netPerformancePercentWithCurrencyEffect;
@ -218,7 +269,7 @@ export class GfTreemapChartComponent
`${netPerformancePercentWithCurrencyEffect > 0 ? '+' : ''}${(ctx.raw._data.netPerformancePercentWithCurrencyEffect * 100).toFixed(2)}%` `${netPerformancePercentWithCurrencyEffect > 0 ? '+' : ''}${(ctx.raw._data.netPerformancePercentWithCurrencyEffect * 100).toFixed(2)}%`
]; ];
}, },
hoverColor: 'white', hoverColor: undefined,
position: 'top' position: 'top'
}, },
spacing: 1, spacing: 1,

Loading…
Cancel
Save