mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Expose radial scale point label positions (#8588)
This commit is contained in:
parent
5a48604df7
commit
275fdaf3da
@ -449,6 +449,7 @@ The private APIs listed below were renamed:
|
||||
* `DatasetController.resyncElements` was renamed to `DatasetController._resyncElements`
|
||||
* `LayoutItem.isFullWidth` was renamed to `LayoutItem.isFullSize`
|
||||
* `RadialLinearScale.setReductions` was renamed to `RadialLinearScale._setReductions`
|
||||
* `RadialLinearScale.pointLabels` was renamed to `RadialLinearScale._pointLabels`
|
||||
* `Scale.handleMargins` was renamed to `Scale._handleMargins`
|
||||
|
||||
### Changed
|
||||
|
||||
@ -90,7 +90,7 @@ function fitWithPointLabels(scale) {
|
||||
const furthestAngles = {};
|
||||
let i, textSize, pointPosition;
|
||||
|
||||
scale._pointLabelSizes = [];
|
||||
const labelSizes = [];
|
||||
|
||||
const valueCount = scale.chart.data.labels.length;
|
||||
for (i = 0; i < valueCount; i++) {
|
||||
@ -98,8 +98,8 @@ function fitWithPointLabels(scale) {
|
||||
const opts = scale.options.pointLabels.setContext(scale.getContext(i));
|
||||
const plFont = toFont(opts.font);
|
||||
scale.ctx.font = plFont.string;
|
||||
textSize = measureLabelSize(scale.ctx, plFont.lineHeight, scale.pointLabels[i]);
|
||||
scale._pointLabelSizes[i] = textSize;
|
||||
textSize = measureLabelSize(scale.ctx, plFont.lineHeight, scale._pointLabels[i]);
|
||||
labelSizes[i] = textSize;
|
||||
|
||||
// Add quarter circle to make degree 0 mean top of circle
|
||||
const angleRadians = scale.getIndexAngle(i);
|
||||
@ -129,6 +129,51 @@ function fitWithPointLabels(scale) {
|
||||
}
|
||||
|
||||
scale._setReductions(scale.drawingArea, furthestLimits, furthestAngles);
|
||||
|
||||
scale._pointLabelItems = [];
|
||||
|
||||
// Now that text size is determined, compute the full positions
|
||||
const opts = scale.options;
|
||||
const tickBackdropHeight = getTickBackdropHeight(opts);
|
||||
const outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
|
||||
|
||||
for (i = 0; i < valueCount; i++) {
|
||||
// Extra pixels out for some label spacing
|
||||
const extra = (i === 0 ? tickBackdropHeight / 2 : 0);
|
||||
const pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5);
|
||||
|
||||
const angle = toDegrees(scale.getIndexAngle(i));
|
||||
const size = labelSizes[i];
|
||||
adjustPointPositionForLabelHeight(angle, size, pointLabelPosition);
|
||||
|
||||
const textAlign = getTextAlignForAngle(angle);
|
||||
let left;
|
||||
|
||||
if (textAlign === 'left') {
|
||||
left = pointLabelPosition.x;
|
||||
} else if (textAlign === 'center') {
|
||||
left = pointLabelPosition.x - (size.w / 2);
|
||||
} else {
|
||||
left = pointLabelPosition.x - size.w;
|
||||
}
|
||||
|
||||
const right = left + size.w;
|
||||
|
||||
scale._pointLabelItems[i] = {
|
||||
// Text position
|
||||
x: pointLabelPosition.x,
|
||||
y: pointLabelPosition.y,
|
||||
|
||||
// Text rendering data
|
||||
textAlign,
|
||||
|
||||
// Bounding box
|
||||
left,
|
||||
top: pointLabelPosition.y,
|
||||
right,
|
||||
bottom: pointLabelPosition.y + size.h,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getTextAlignForAngle(angle) {
|
||||
@ -153,31 +198,24 @@ function drawPointLabels(scale) {
|
||||
const ctx = scale.ctx;
|
||||
const opts = scale.options;
|
||||
const pointLabelOpts = opts.pointLabels;
|
||||
const tickBackdropHeight = getTickBackdropHeight(opts);
|
||||
const outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
|
||||
|
||||
ctx.save();
|
||||
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
for (let i = scale.chart.data.labels.length - 1; i >= 0; i--) {
|
||||
// Extra pixels out for some label spacing
|
||||
const extra = (i === 0 ? tickBackdropHeight / 2 : 0);
|
||||
const pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5);
|
||||
|
||||
const optsAtIndex = pointLabelOpts.setContext(scale.getContext(i));
|
||||
const plFont = toFont(optsAtIndex.font);
|
||||
const angle = toDegrees(scale.getIndexAngle(i));
|
||||
adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition);
|
||||
const {x, y, textAlign} = scale._pointLabelItems[i];
|
||||
renderText(
|
||||
ctx,
|
||||
scale.pointLabels[i],
|
||||
pointLabelPosition.x,
|
||||
pointLabelPosition.y + (plFont.lineHeight / 2),
|
||||
scale._pointLabels[i],
|
||||
x,
|
||||
y + (plFont.lineHeight / 2),
|
||||
plFont,
|
||||
{
|
||||
color: optsAtIndex.color,
|
||||
textAlign: getTextAlignForAngle(angle),
|
||||
textAlign: textAlign,
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -238,7 +276,8 @@ export default class RadialLinearScale extends LinearScaleBase {
|
||||
/** @type {number} */
|
||||
this.drawingArea = undefined;
|
||||
/** @type {string[]} */
|
||||
this.pointLabels = [];
|
||||
this._pointLabels = [];
|
||||
this._pointLabelItems = [];
|
||||
}
|
||||
|
||||
setDimensions() {
|
||||
@ -278,7 +317,7 @@ export default class RadialLinearScale extends LinearScaleBase {
|
||||
LinearScaleBase.prototype.generateTickLabels.call(me, ticks);
|
||||
|
||||
// Point labels
|
||||
me.pointLabels = me.chart.data.labels.map((value, index) => {
|
||||
me._pointLabels = me.chart.data.labels.map((value, index) => {
|
||||
const label = callCallback(me.options.pointLabels.callback, [value, index], me);
|
||||
return label || label === 0 ? label : '';
|
||||
});
|
||||
@ -380,6 +419,16 @@ export default class RadialLinearScale extends LinearScaleBase {
|
||||
return this.getPointPositionForValue(index || 0, this.getBaseValue());
|
||||
}
|
||||
|
||||
getPointLabelPosition(index) {
|
||||
const {left, top, right, bottom} = this._pointLabelItems[index];
|
||||
return {
|
||||
left,
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
|
||||
@ -324,7 +324,7 @@ describe('Test the radial linear scale', function() {
|
||||
});
|
||||
|
||||
expect(getLabels(chart.scales.r)).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']);
|
||||
expect(chart.scales.r.pointLabels).toEqual(['label1', 'label2', 'label3', 'label4', 'label5']);
|
||||
expect(chart.scales.r._pointLabels).toEqual(['label1', 'label2', 'label3', 'label4', 'label5']);
|
||||
});
|
||||
|
||||
it('Should build point labels using the user supplied callback', function() {
|
||||
@ -349,7 +349,7 @@ describe('Test the radial linear scale', function() {
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.scales.r.pointLabels).toEqual(['0', '1', '2', '3', '4']);
|
||||
expect(chart.scales.r._pointLabels).toEqual(['0', '1', '2', '3', '4']);
|
||||
});
|
||||
|
||||
it('Should build point labels from falsy values', function() {
|
||||
@ -363,7 +363,7 @@ describe('Test the radial linear scale', function() {
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.scales.r.pointLabels).toEqual([0, '', '', '', '', '']);
|
||||
expect(chart.scales.r._pointLabels).toEqual([0, '', '', '', '', '']);
|
||||
});
|
||||
|
||||
it('should correctly set the center point', function() {
|
||||
|
||||
1
types/index.esm.d.ts
vendored
1
types/index.esm.d.ts
vendored
@ -3089,6 +3089,7 @@ export interface RadialLinearScale<O extends RadialLinearScaleOptions = RadialLi
|
||||
getValueForDistanceFromCenter(distance: number): number;
|
||||
getPointPosition(index: number, distanceFromCenter: number): { x: number; y: number; angle: number };
|
||||
getPointPositionForValue(index: number, value: number): { x: number; y: number; angle: number };
|
||||
getPointLabelPosition(index: number): ChartArea;
|
||||
getBasePosition(index: number): { x: number; y: number; angle: number };
|
||||
}
|
||||
export const RadialLinearScale: ChartComponent & {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user