function getTypeSizes(
width,
height,
primaryText,
secondaryText,
changeIndicator
) {
const MIN_FONT_SIZE = 12;
const fontBins = [
{
primarySize: MIN_FONT_SIZE,
secondaryMaxRatio: 0.9,
ciMaxRatio: 0.9,
timeLabelRatio: 0
},
{
primarySize: 18,
secondaryMaxRatio: 0.9,
ciMaxRatio: 0.9,
timeLabelRatio: 0
},
{
primarySize: 24,
secondaryMaxRatio: 0.9,
ciMaxRatio: 0.75,
timeLabelRatio: 0
},
{
primarySize: 36,
secondaryMaxRatio: 0.75,
ciMaxRatio: 0.6,
timeLabelRatio: 0
},
{
primarySize: 42,
secondaryMaxRatio: 0.6,
ciMaxRatio: 0.5,
timeLabelRatio: 0.25 // 42px
},
{
primarySize: 64,
secondaryMaxRatio: 0.5,
ciMaxRatio: 0.4,
timeLabelRatio: 0.2 // 64px
},
{
primarySize: 80,
secondaryMaxRatio: 0.5,
ciMaxRatio: 0.4,
timeLabelRatio: 0.175 // 80px
},
{
primarySize: 96,
secondaryMaxRatio: 0.5,
ciMaxRatio: 0.4,
timeLabelRatio: 0.15 // 96px
},
{
primarySize: 130,
secondaryMaxRatio: 0.5,
ciMaxRatio: 0.4,
timeLabelRatio: 0.15 // 130px
},
{
primarySize: 260,
secondaryMaxRatio: 0.5,
ciMaxRatio: 0.4,
timeLabelRatio: 0.15 // 260px
},
{
primarySize: 320,
secondaryMaxRatio: 0.5,
ciMaxRatio: 0.4,
timeLabelRatio: 0.125 // 320px
}
];
const binFontSize = (fontSize) => {
const nextLargerIndex = fontBins.findIndex((b) => b.primarySize > fontSize);
if (nextLargerIndex === 0 || Number.isNaN(fontSize)) return fontBins[0];
if (nextLargerIndex === -1) return fontBins[fontBins.length - 1];
return fontBins[nextLargerIndex - 1];
};
const ONE_LINE_MARGIN = 3;
const FONT_FAMILY =
"'NotoSans', 'Lucida Grande', 'Lucida Sans Unicode', sans-serif";
// Get text measurements
const primaryWidth = d3
.select(svg2)
.select("text.pText")
.node()
.getBBox().width;
const secondaryWidth = secondaryText
? d3.select(svg2).select("text.sText").node().getBBox().width
: 0;
const changeIndicatorWidth = changeIndicator
? d3.select(svg2).select("text.ciText").node().getBBox().width
: 0;
// Padding calculations
const pX = Math.min(40, width * 0.2);
const pY = height * 0.3;
// Always use two-line layout when change indicator is present
const layoutTwoLines = changeIndicator ? true : false;
// Calculate sizes for primary + secondary (first line)
const firstLineFactor = Math.min(
(height - pY) / TEST_SIZE / (1.5 * RENDER_HEIGHT_FACTOR + 0.25),
(width - pX) / (primaryWidth + secondaryWidth + ONE_LINE_MARGIN)
);
const binnedSize = binFontSize(firstLineFactor * TEST_SIZE);
const { primarySize, secondaryMaxRatio, ciMaxRatio } = binnedSize;
// Calculate secondary size
const secondaryWidthAvail =
width - pX - ONE_LINE_MARGIN - (primarySize * primaryWidth) / TEST_SIZE;
const secondaryHeightAvail = height - pY;
const secondaryFactor = Math.min(
secondaryWidthAvail / secondaryWidth,
secondaryHeightAvail / (TEST_SIZE * 0.5 * RENDER_HEIGHT_FACTOR)
);
const secondarySize = Math.max(
MIN_FONT_SIZE,
Math.min(primarySize * secondaryMaxRatio, secondaryFactor * TEST_SIZE * 0.5)
);
// Calculate change indicator size
let changeIndicatorSize = 0;
if (changeIndicator) {
const ciWidthAvail = width - pX;
const ciHeightAvail =
height - pY - (RENDER_HEIGHT_FACTOR + 0.25) * primarySize;
const ciFactor = Math.min(
ciWidthAvail / changeIndicatorWidth,
ciHeightAvail / (TEST_SIZE * 0.5 * RENDER_HEIGHT_FACTOR)
);
changeIndicatorSize = Math.max(
MIN_FONT_SIZE,
Math.min(primarySize * ciMaxRatio, ciFactor * TEST_SIZE * 0.5)
// Math.min(primarySize * ciMaxRatio, ciFactor * TEST_SIZE)
);
}
// Add time label size calculation
let timeLabelSize = 0;
const { timeLabelRatio } = binnedSize;
timeLabelSize = primarySize * timeLabelRatio;
return {
primarySize,
secondarySize,
changeIndicatorSize,
timeLabelSize,
numLines: layoutTwoLines ? 2 : 1
};
}