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 fit option when the label is overflowing the rectangle #175

Merged
merged 3 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/samples/zoom.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const config = {
font: {
size: 16
},
overflow: 'hidden'
overflow: 'fit'
}
}
],
Expand Down
1 change: 1 addition & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ The overflow property controls what happens to a label that is too big to fit in

* `cut`: if the label is too big, it will be cut to stay inside the rectangle. It is the default.
* `hidden`: the label is removed altogether if the rectangle is too small for it.
* `fit`: the label will be automatically fit inside the rectangle if its dimension is bigger than the rectangle size.

### Position

Expand Down
34 changes: 28 additions & 6 deletions src/element.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Element} from 'chart.js';
import {toFont, isArray, toTRBL, toTRBLCorners, addRoundedRectPath, valueOrDefault, defined} from 'chart.js/helpers';
import {toFont, isArray, toTRBL, toTRBLCorners, addRoundedRectPath, valueOrDefault, defined, isNumber} from 'chart.js/helpers';

const widthCache = new Map();

Expand Down Expand Up @@ -164,29 +164,51 @@ function measureLabelSize(ctx, lines, fonts) {
return widthCache.get(mapKey);
}

function toFonts(fonts, fitRatio) {
return fonts.map(function(f) {
f.size = Math.floor(f.size * fitRatio);
f.lineHeight = undefined;
return toFont(f);
});
}

function labelToDraw(ctx, rect, options, labelSize) {
const {overflow, padding} = options;
const {width, height} = labelSize;
if (overflow === 'hidden') {
return !((width + padding * 2) > rect.w || (height + padding * 2) > rect.h);
} else if (overflow === 'fit') {
const ratio = Math.min(rect.w / (width + padding * 2), rect.h / (height + padding * 2));
if (ratio < 1) {
return ratio;
}
}
return true;
}

function getFontFromOptions(rect, labels) {
const {font, hoverFont} = labels;
const optFont = (rect.active ? hoverFont : font) || font;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm going in circles, but again was it so that the sub-objects (labels in this case) don't automatically resolve the hover options?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes @kurkle
There was also an issue that we closed with a patch. Hover font seems not solved. But tomorrow I want to understand better the current logic in chartjs and why is not applied here for font. Ok for you?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but I'll merge this already anyway :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kurkle please, don't hate me if you can... when you have time, we should go ahead with PRs on the annotation, I think...

return isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)];
}

function drawLabel(ctx, rect, options) {
const labels = options.labels;
const content = labels.formatter;
if (!content) {
return;
}
const contents = isArray(content) ? content : [content];
const {font, hoverFont} = labels;
const optFont = (rect.active ? hoverFont : font) || font;
const fonts = isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)];
const labelSize = measureLabelSize(ctx, contents, fonts);
if (!labelToDraw(ctx, rect, labels, labelSize)) {
let fonts = getFontFromOptions(rect, labels);
let labelSize = measureLabelSize(ctx, contents, fonts);
const lblToDraw = labelToDraw(ctx, rect, labels, labelSize);
if (!lblToDraw) {
return;
}
if (isNumber(lblToDraw)) {
labelSize = {width: labelSize.width * lblToDraw, height: labelSize.height * lblToDraw};
fonts = toFonts(fonts, lblToDraw);
}
const {color, hoverColor, align} = labels;
const optColor = (rect.active ? hoverColor : color) || color;
const colors = isArray(optColor) ? optColor : [optColor];
Expand Down
29 changes: 29 additions & 0 deletions test/fixtures/basic/labelsOverflowFit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default {
tolerance: 0.0075,
config: {
type: 'treemap',
data: {
datasets: [{
label: 'Simple treemap',
data: [6, 6, 6, 4, 4, 2, 1, 1, 1, 1, 1, 1],
backgroundColor: 'red',
labels: {
display: true,
overflow: 'fit',
font: {
size: 64
}
}
}]
},
options: {
events: []
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Binary file added test/fixtures/basic/labelsOverflowFit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion types/index.esm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export type LabelPosition = 'top' | 'middle' | 'bottom';

export type LabelAlign = 'left' | 'center' | 'right';

export type LabelOverflow = 'cut' | 'hidden';
export type LabelOverflow = 'cut' | 'hidden' | 'fit';

type TreemapControllerDatasetDividersOptions = {
display?: boolean,
Expand Down