I have provided the code where I am plotting 9 traces using Plotly.js and have
formatted the Y-axis scale by calling formatYAxisScale. However, the formatting is not retained when I download the image. Could I get some insight on why this is
happening and how I can ensure the Y-axis formatting is preserved in
the downloaded image?
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
import * as Plotly from 'plotly.js-dist-min';
import { CurrencyFormatterPipe } from '../pipes/currency-formatter.pipe';
@Directive({
selector: '[appUndiscountedCashflowPlotly]',
})
export class UndiscountedCashflowPlotlyDirective implements OnInit {
@Input() public data: any;
protected plot: any;
constructor(
protected elementRef: ElementRef,
private currencyFormatterPipe: CurrencyFormatterPipe
) {}
ngOnInit() {
this.plot = this.elementRef.nativeElement;
const labels = this.data.map((entry: { Year: any }) => entry.Year);
const trace: any = [];
const layout: Partial<Plotly.Layout> = {
barmode: 'relative',
showlegend: true,
legend: {
orientation: 'h', /// Horizontal layout
yanchor: 'top', /// Align to the top of the legend box
y: 1.4, /// Align legends to the bottom
xanchor: 'left',
x: 0, /// Align legends to the left
font: { size: 12 },
traceorder: 'normal',
},
autosize: true,
xaxis: {
title: {
text: 'Year',
font: { size: 14, color: '#000000' },
},
tickfont: { size: 12, color: '#000000' },
tickmode: 'linear', /// Use linear mode for ticks
dtick: 1, /// Set tick interval to 1
fixedrange: true,
showline: true,
},
yaxis: {
title: {
text: 'Millions',
font: { size: 14, color: '#000000' },
standoff: 20, /// Adds space between the title and the axis
},
tickfont: { size: 12, color: '#000000' },
showline: true,
zeroline: true,
fixedrange: true,
automargin: true,
},
margin: {
t: 30,
b: 50,
l: 30,
r: 30, /// Adjust margins for better layout
},
dragmode: undefined, /// Disable dragging for zoom/pan
plot_bgcolor: '#F8F8F8',
paper_bgcolor: '#F8F8F8',
};
const options: Partial<Plotly.Config> = {
responsive: true,
displayModeBar: true,
modeBarButtonsToRemove: [
'select2d',
'lasso2d',
] as Plotly.ModeBarDefaultButtons[], // Disable box and lasso select
toImageButtonOptions: {
format: 'png',
filename: 'Cashflow Breakdown (Undiscounted)',
width: 1000,
scale: 1,
},
displaylogo: false,
};
Plotly.newPlot(this.plot, trace, layout, options)
.then(() =>
this.formatYAxisScale()
);
/// Listen to the relayout event
this.plot.on('plotly_relayout', () => {
this.formatYAxisScale(); // Reapply formatting after plot resize or layout change
});
/// Listen to the restyle(legend click) event
this.plot.on('plotly_restyle', () => {
this.formatYAxisScale(); // Reapply formatting after plot resize or layout change
});
}
///Format y axis currency
private formatYAxisScale() {
const yTicks = this.plot.querySelectorAll('.ytick text');
yTicks.forEach((tick: any) => {
const sanitizedValue = tick.__data__.text
.replace(/−/g, '-')
.replace(/,/g, '');
const numericPart = parseFloat(sanitizedValue);
const suffix = sanitizedValue.match(/[a-zA-Z]+/g)
? sanitizedValue.match(/[a-zA-Z]+/g)[0]
: '';
if (!isNaN(numericPart)) {
if (suffix === 'M' && numericPart > 0 && numericPart < 1) {
const convertedValue = numericPart * 1000; /// .2M => 200, .4M => 400
tick.textContent = `${convertedValue}K`;
} else if (suffix === 'M' && numericPart < 0) {
const absoluteValue = Math.abs(numericPart);
tick.textContent = `$(${absoluteValue})`; /// Display as $(6)
} else {
let formattedValue = this.currencyFormatterPipe.transform(
numericPart,
true,
false,
true,
true
);
if (formattedValue !== null) {
if (suffix !== 'M') { /// For positive values with suffix, just add the suffix back
formattedValue += suffix;
}
tick.textContent = formattedValue;
}
}
}
});
}
}