Skip to content

Commit

Permalink
fix chartjs#10836 - add publc getLabelItems()
Browse files Browse the repository at this point in the history
  • Loading branch information
cmcnulty committed Nov 2, 2022
1 parent d64cfe5 commit 472b04e
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 17 deletions.
40 changes: 24 additions & 16 deletions src/core/core.scale.js
Expand Up @@ -364,6 +364,14 @@ export default class Scale extends Element {
return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];
}

/**
* @return {import('../types').LabelItem[]}
*/
getLabelItems(chartArea = this.chart.chartArea) {
const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
return items;
}

// When a new layout is created, reset the data limits cache
beforeLayout() {
this._cache = {};
Expand Down Expand Up @@ -1292,17 +1300,20 @@ export default class Scale extends Element {
}

items.push({
rotation,
label,
font,
color,
strokeColor,
strokeWidth,
textOffset,
textAlign: tickTextAlign,
textBaseline,
translation: [x, y],
backdrop,
renderTextOptions: {
rotation,
color,
strokeColor,
strokeWidth,
textOffset,
textAlign: tickTextAlign,
textBaseline,
translation: [x, y],
backdrop,
}
});
}

Expand Down Expand Up @@ -1549,16 +1560,13 @@ export default class Scale extends Element {
clipArea(ctx, area);
}

const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
let i, ilen;

for (i = 0, ilen = items.length; i < ilen; ++i) {
const item = items[i];
const items = this.getLabelItems(chartArea);
for (const item of items) {
const renderTextOptions = item.renderTextOptions;
const tickFont = item.font;
const label = item.label;

let y = item.textOffset;
renderText(ctx, label, 0, y, tickFont, item);
const y = item.textOffset;
renderText(ctx, label, 0, y, tickFont, renderTextOptions);
}

if (area) {
Expand Down
128 changes: 128 additions & 0 deletions test/specs/core.scale.tests.js
Expand Up @@ -571,4 +571,132 @@ describe('Core.scale', function() {
expect(chart.scales.y.max).toEqual(10);
});
});

describe('overrides', () => {
it('should create new scale', () => {
const chart = window.acquireChart({
type: 'scatter',
data: {
datasets: [{
data: [{x: 100, y: 100}, {x: -100, y: -100}]
}, {
data: [{x: 10, y: 10}, {x: -10, y: -10}]
}]
},
options: {
scales: {
x2: {
type: 'linear',
min: -20,
max: 20
}
}
}
});

expect(Object.keys(chart.scales).sort()).toEqual(['x', 'x2', 'y']);
});

it('should create new scale with custom name', () => {
const chart = window.acquireChart({
type: 'scatter',
data: {
datasets: [{
data: [{x: 100, y: 100}, {x: -100, y: -100}]
}, {
data: [{x: 10, y: 10}, {x: -10, y: -10}]
}]
},
options: {
scales: {
scaleX: {
axis: 'x',
type: 'linear',
min: -20,
max: 20
}
}
}
});

expect(Object.keys(chart.scales).sort()).toEqual(['scaleX', 'x', 'y']);
});

it('should throw error on scale with custom name without axis type', () => {
expect(() => window.acquireChart({
type: 'scatter',
data: {
datasets: [{
data: [{x: 100, y: 100}, {x: -100, y: -100}]
}, {
data: [{x: 10, y: 10}, {x: -10, y: -10}]
}]
},
options: {
scales: {
scaleX: {
type: 'linear',
min: -20,
max: 20
}
}
}
})).toThrow();
});

it('should read options first to determine axis', () => {
const chart = window.acquireChart({
type: 'scatter',
data: {
datasets: [{
data: [{x: 100, y: 100}, {x: -100, y: -100}]
}, {
data: [{x: 10, y: 10}, {x: -10, y: -10}]
}]
},
options: {
scales: {
xavier: {
axis: 'y',
type: 'linear',
min: -20,
max: 20
}
}
}
});

expect(chart.scales.xavier.axis).toBe('y');
});
it('should center labels when rotated in x axis', () => {
const chart = window.acquireChart({
type: 'line',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3]
}]
},
options: {
scales: {
x: {
ticks: {
minRotation: 90,
}
}
}
}
});
const mapper = item => parseFloat(item.renderTextOptions.translation[0].toFixed(2));
const expected = [20.15, 113.6, 207.05, 300.5, 393.95, 487.4];
const actual = chart.scales.x.getLabelItems().map(mapper);
const len = expected.length;
for (let i = 0; i < len; ++i) {
const actualValue = actual[i];
const expectedValue = expected[i];
expect(actualValue).toBeCloseTo(expectedValue, 1);
}
});
});
});
34 changes: 33 additions & 1 deletion types/helpers/helpers.canvas.d.ts
@@ -1,4 +1,4 @@
import { PointStyle } from '../index.esm';
import { PointStyle, Scriptable, ScriptableScaleContext } from '../index.esm';
import { Color } from '../color';
import { ChartArea, RoundedRect } from '../geometric';
import { CanvasFontSpec } from './helpers.options';
Expand Down Expand Up @@ -89,6 +89,38 @@ export interface RenderTextOpts {
* Underline the text
*/
underline?: boolean;

/**
* Dimensions for drawing the label backdrop
*/
backdrop?: BackdropOptions;
}

export interface BackdropOptions {
/**
* Left position of backdrop as pixel
*/
left: number;

/**
* Top position of backdrop as pixel
*/
top: number;

/**
* Width of backdrop in pixels
*/
width: number;

/**
* Height of backdrop in pixels
*/
height: number;

/**
* Color of label backdrops.
*/
color: Scriptable<Color, ScriptableScaleContext>;
}

export function renderText(
Expand Down
9 changes: 9 additions & 0 deletions types/index.esm.d.ts
Expand Up @@ -7,6 +7,8 @@ import { Color } from './color';
import { Element } from './element';
import { ChartArea, Point } from './geometric';
import { LayoutItem, LayoutPosition } from './layout';
import { RenderTextOpts } from './helpers/helpers.canvas';
import { CanvasFontSpec } from './helpers';

export { DateAdapter, TimeUnit, _adapters } from './adapters';
export { Animation, Animations, Animator, AnimationEvent } from './animation';
Expand Down Expand Up @@ -1309,6 +1311,7 @@ export interface Scale<O extends CoreScaleOptions = CoreScaleOptions> extends El
getMinMax(canStack: boolean): { min: number; max: number };
getTicks(): Tick[];
getLabels(): string[];
getLabelItems(chartArea?: ChartArea): LabelItem[];
beforeUpdate(): void;
configure(): void;
afterUpdate(): void;
Expand Down Expand Up @@ -1352,6 +1355,12 @@ export interface ScriptableScalePointLabelContext {
type: string;
}

export interface LabelItem {
label: string | string[];
font: CanvasFontSpec;
textOffset: number;
renderTextOptions: RenderTextOpts;
}

export const Ticks: {
formatters: {
Expand Down

0 comments on commit 472b04e

Please sign in to comment.