BarChart: when horiz, allow rotation and skipping of y tick labels (#59354)

This commit is contained in:
Leon Sorokin 2022-11-29 20:46:39 -06:00 committed by GitHub
parent ce0bdb2cd9
commit 122f0d947e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 429 additions and 67 deletions

View File

@ -6929,11 +6929,12 @@ exports[`better eslint`] = {
"public/app/plugins/panel/barchart/bars.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Do not use any type assertions.", "6"]
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Do not use any type assertions.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Do not use any type assertions.", "7"]
],
"public/app/plugins/panel/barchart/module.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@ -6944,7 +6945,8 @@ exports[`better eslint`] = {
],
"public/app/plugins/panel/barchart/utils.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/plugins/panel/candlestick/CandlestickPanel.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],

View File

@ -0,0 +1,320 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 530,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"fillOpacity": 80,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineWidth": 1,
"scaleDistribution": {
"type": "linear"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
},
"unit": "decmbytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 11,
"x": 0,
"y": 0
},
"id": 2,
"maxDataPoints": 30,
"options": {
"barRadius": 0,
"barWidth": 0.97,
"groupWidth": 0.7,
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"orientation": "vertical",
"showValue": "auto",
"stacking": "none",
"tooltip": {
"mode": "single",
"sort": "none"
},
"xTickLabelMaxLength": 6,
"xTickLabelRotation": 45,
"xTickLabelSpacing": 100
},
"targets": [
{
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A"
},
"rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"label\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 600000\n }\n },\n {\n \"name\": \"A-series\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {},\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n \"acquisition\",\n \"extension\",\n \"conductor\",\n \"authorise\",\n \"architect\",\n \"illusion\",\n \"congress\",\n \"highlight\",\n \"partnership\",\n \"understanding\",\n \"disagreement\",\n \"personality\",\n \"commerce\",\n \"systematic\",\n \"hesitate\",\n \"business\",\n \"manufacture\",\n \"incredible\",\n \"constitutional\",\n \"prevalence\",\n \"professor\",\n \"entitlement\",\n \"cooperation\",\n \"sickness\",\n \"contrast\",\n \"reference\",\n \"audience\",\n \"discount\",\n \"apparatus\",\n \"disturbance\",\n \"automatic\",\n \"refrigerator\",\n \"elaborate\",\n \"sympathetic\",\n \"integration\",\n \"president\"\n ],\n [\n 306.78931659492116,\n 200.00696051101917,\n 164.90889283973593,\n 518.9385023737021,\n 999.9040675564702,\n 613.9689830172349,\n 773.2337077340269,\n 317.47395634701644,\n 748.3318338316539,\n 606.8039493787173,\n 426.27771317792866,\n 376.47735643253924,\n 66.30635081800493,\n 401.70654338415505,\n 108.86259550477234,\n 182.40284186231278,\n 867.7047958572101,\n 959.3957783599242,\n 396.7606089549935,\n 455.9625595614323,\n 685.4792456298062,\n 368.6567303946707,\n 157.06596562976327,\n 59.54120602048763,\n 406.72723615743973,\n 440.18247585615575,\n 516.0267558264891,\n 258.76006051667315,\n 952.966531725171,\n 554.8746357628739,\n 86.7279280805682,\n 781.2422516386563,\n 754.2723802427706,\n 435.0305712850233,\n 384.43181614983,\n 459.04164596738127\n ]\n ]\n }\n }\n]",
"refId": "A",
"scenarioId": "raw_frame"
}
],
"title": "Panel Title",
"type": "barchart"
},
{
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"axisSoftMin": 0,
"fillOpacity": 80,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineWidth": 0,
"scaleDistribution": {
"type": "linear"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 7,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 13,
"x": 11,
"y": 0
},
"id": 5,
"options": {
"barRadius": 0,
"barWidth": 1,
"groupWidth": 0.82,
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "right",
"showLegend": true
},
"orientation": "horizontal",
"showValue": "auto",
"stacking": "none",
"text": {},
"tooltip": {
"mode": "single",
"sort": "none"
},
"xTickLabelRotation": 45,
"xTickLabelSpacing": 0
},
"targets": [
{
"csvContent": "Name,Stat1,Stat2\nStockholm, 10, 15\nNew York, 19, -5\nLondon, 10, 1\nLong value, 15,10",
"refId": "A",
"scenarioId": "csv_content"
}
],
"title": "Auto sizing & auto show values",
"type": "barchart"
},
{
"datasource": {
"type": "datasource",
"uid": "-- Dashboard --"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"fillOpacity": 80,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineWidth": 1,
"scaleDistribution": {
"type": "linear"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
},
"unit": "decmbytes"
},
"overrides": []
},
"gridPos": {
"h": 18,
"w": 24,
"x": 0,
"y": 14
},
"id": 3,
"maxDataPoints": 20,
"options": {
"barRadius": 0,
"barWidth": 0.97,
"groupWidth": 0.7,
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"orientation": "horizontal",
"showValue": "auto",
"stacking": "none",
"tooltip": {
"mode": "single",
"sort": "none"
},
"xTickLabelMaxLength": 5,
"xTickLabelRotation": 45,
"xTickLabelSpacing": 100
},
"targets": [
{
"datasource": {
"type": "datasource",
"uid": "-- Dashboard --"
},
"panelId": 2,
"refId": "A"
}
],
"title": "Panel Title",
"type": "barchart"
}
],
"schemaVersion": 37,
"style": "dark",
"tags": [
"gdev",
"panel-tests",
"barchart",
"graph-ng"
],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "BarChart - Label Rotation & Skipping",
"uid": "xCmMwXdVz",
"version": 20,
"weekStart": ""
}

View File

@ -107,6 +107,13 @@ local dashboard = grafana.dashboard;
id: 0,
}
},
dashboard.new('barchart-label-rotation-skipping', import '../dev-dashboards/panel-barchart/barchart-label-rotation-skipping.json') +
resource.addMetadata('folder', 'dev-dashboards') +
{
spec+: {
id: 0,
}
},
dashboard.new('barchart-thresholds-mappings', import '../dev-dashboards/panel-barchart/barchart-thresholds-mappings.json') +
resource.addMetadata('folder', 'dev-dashboards') +
{

View File

@ -13,7 +13,7 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 1`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -40,7 +40,7 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 1`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,
@ -167,7 +167,7 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 2`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -194,7 +194,7 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 2`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,
@ -348,7 +348,7 @@ exports[`BarChart utils preparePlotConfigBuilder orientation 3`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": 0,
"scale": "m/s",
"show": true,
"side": 3,
@ -475,7 +475,7 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 1`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -502,7 +502,7 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 1`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,
@ -629,7 +629,7 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 2`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -656,7 +656,7 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 2`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,
@ -783,7 +783,7 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 3`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -810,7 +810,7 @@ exports[`BarChart utils preparePlotConfigBuilder stacking 3`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,
@ -937,7 +937,7 @@ exports[`BarChart utils preparePlotConfigBuilder value visibility 1`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -964,7 +964,7 @@ exports[`BarChart utils preparePlotConfigBuilder value visibility 1`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,
@ -1091,7 +1091,7 @@ exports[`BarChart utils preparePlotConfigBuilder value visibility 2`] = `
"width": 1,
},
"labelGap": 0,
"rotate": -0,
"rotate": 0,
"scale": "x",
"show": true,
"side": 3,
@ -1118,7 +1118,7 @@ exports[`BarChart utils preparePlotConfigBuilder value visibility 2`] = `
"width": 1,
},
"labelGap": 0,
"rotate": undefined,
"rotate": -0,
"scale": "m/s",
"show": true,
"side": 2,

View File

@ -51,6 +51,7 @@ export interface BarsOptions {
getColor?: (seriesIdx: number, valueIdx: number, value: any) => string | null;
fillOpacity?: number;
formatValue: (seriesIdx: number, value: any) => string;
formatShortValue: (seriesIdx: number, value: any) => string;
timeZone?: TimeZone;
text?: VizTextDisplayOptions;
onHover?: (seriesIdx: number, valueIdx: number) => void;
@ -116,7 +117,17 @@ function calculateFontSizeWithMetrics(
* @internal
*/
export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
const { xOri, xDir: dir, rawValue, getColor, formatValue, fillOpacity = 1, showValue, xSpacing = 0 } = opts;
const {
xOri,
xDir: dir,
rawValue,
getColor,
formatValue,
formatShortValue,
fillOpacity = 1,
showValue,
xSpacing = 0,
} = opts;
const isXHorizontal = xOri === ScaleOrientation.Horizontal;
const hasAutoValueSize = !Boolean(opts.text?.valueSize);
const isStacked = opts.stacking !== StackingMode.None;
@ -131,35 +142,34 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
let qt: Quadtree;
let hRect: Rect | null;
const xSplits: Axis.Splits = (u: uPlot) => {
const dim = isXHorizontal ? u.bbox.width : u.bbox.height;
const _dir = dir * (isXHorizontal ? 1 : -1);
// for distr: 2 scales, the splits array should contain indices into data[0] rather than values
const xSplits: Axis.Splits | undefined = (u) => Array.from(u.data[0].map((v, i) => i));
let dataLen = u.data[0].length;
let lastIdx = dataLen - 1;
const hFilter: Axis.Filter | undefined =
xSpacing === 0
? undefined
: (u, splits) => {
// hSpacing?
const dim = u.bbox.width;
const _dir = dir * (isXHorizontal ? 1 : -1);
let skipMod = 0;
let dataLen = splits.length;
let lastIdx = dataLen - 1;
if (xSpacing !== 0) {
let cssDim = dim / devicePixelRatio;
let maxTicks = Math.abs(Math.floor(cssDim / xSpacing));
let skipMod = 0;
skipMod = dataLen < maxTicks ? 0 : Math.ceil(dataLen / maxTicks);
}
let cssDim = dim / uPlot.pxRatio;
let maxTicks = Math.abs(Math.floor(cssDim / xSpacing));
let splits: number[] = [];
skipMod = dataLen < maxTicks ? 0 : Math.ceil(dataLen / maxTicks);
// for distr: 2 scales, the splits array should contain indices into data[0] rather than values
u.data[0].forEach((v, i) => {
let shouldSkip = skipMod !== 0 && (xSpacing > 0 ? i : lastIdx - i) % skipMod > 0;
let splits2 = splits.map((v, i) => {
let shouldSkip = skipMod !== 0 && (xSpacing > 0 ? i : lastIdx - i) % skipMod > 0;
return shouldSkip ? null : v;
});
if (!shouldSkip) {
splits.push(i);
}
});
return _dir === 1 ? splits : splits.reverse();
};
return _dir === 1 ? splits2 : splits2.reverse();
};
// the splits passed into here are data[0] values looked up by the indices returned from splits()
const xValues: Axis.Values = (u, splits, axisIdx, foundSpace, foundIncr) => {
@ -182,7 +192,7 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
return vals;
}
return splits.map((v) => formatValue(0, v));
return splits.map((v) => (isXHorizontal ? formatShortValue(0, v) : formatValue(0, v)));
};
// this expands the distr: 2 scale so that the indicies of each data[0] land at the proper justified positions
@ -434,8 +444,8 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
if (seriesIdx === 1) {
hRect = null;
let cx = u.cursor.left! * devicePixelRatio;
let cy = u.cursor.top! * devicePixelRatio;
let cx = u.cursor.left! * uPlot.pxRatio;
let cy = u.cursor.top! * uPlot.pxRatio;
qt.get(cx, cy, 1, 1, (o) => {
if (pointWithin(cx, cy, o.x, o.y, o.x + o.w, o.y + o.h)) {
@ -471,10 +481,10 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
}
return {
left: isHovered ? (hRect!.x + widthReduce) / devicePixelRatio : -10,
top: isHovered ? hRect!.y / devicePixelRatio : -10,
width: isHovered ? (hRect!.w - widthReduce) / devicePixelRatio : 0,
height: isHovered ? (hRect!.h - heightReduce) / devicePixelRatio : 0,
left: isHovered ? (hRect!.x + widthReduce) / uPlot.pxRatio : -10,
top: isHovered ? hRect!.y / uPlot.pxRatio : -10,
width: isHovered ? (hRect!.w - widthReduce) / uPlot.pxRatio : 0,
height: isHovered ? (hRect!.h - heightReduce) / uPlot.pxRatio : 0,
};
},
},
@ -634,6 +644,7 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
xRange,
xValues,
xSplits,
hFilter,
barsBuilder,

View File

@ -138,7 +138,7 @@ export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(BarChartPa
})
.addSliderInput({
path: 'xTickLabelRotation',
name: 'Rotate bar labels',
name: 'Rotate X tick labels',
defaultValue: defaultPanelOptions.xTickLabelRotation,
settings: {
min: -90,
@ -147,18 +147,16 @@ export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(BarChartPa
marks: { '-90': '-90°', '-45': '-45°', 0: '0°', 45: '45°', 90: '90°' },
included: false,
},
showIf: (opts) => {
return opts.orientation === VizOrientation.Auto || opts.orientation === VizOrientation.Vertical;
},
})
.addNumberInput({
path: 'xTickLabelMaxLength',
name: 'Bar label max length',
description: 'Bar labels will be truncated to the length provided',
name: 'X tick label max length',
description: 'X labels will be truncated to the length provided',
settings: {
placeholder: 'None',
min: 0,
},
showIf: (opts) => opts.xTickLabelRotation !== 0,
})
.addCustomEditor({
id: 'xTickLabelSpacing',

View File

@ -81,15 +81,18 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
timeZone,
}) => {
const builder = new UPlotConfigBuilder();
const defaultValueFormatter = (seriesIdx: number, value: any) => {
return shortenValue(formattedValueToString(frame.fields[seriesIdx].display!(value)), xTickLabelMaxLength);
const formatValue = (seriesIdx: number, value: any) => {
return formattedValueToString(frame.fields[seriesIdx].display!(value));
};
const formatShortValue = (seriesIdx: number, value: any) => {
return shortenValue(formatValue(seriesIdx, value), xTickLabelMaxLength);
};
// bar orientation -> x scale orientation & direction
const vizOrientation = getBarCharScaleOrientation(orientation);
const formatValue = defaultValueFormatter;
// Use bar width when only one field
if (frame.fields.length === 2) {
groupWidth = barWidth;
@ -107,6 +110,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
getColor,
fillOpacity,
formatValue,
formatShortValue,
timeZone,
text,
showValue,
@ -126,8 +130,13 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
builder.setTooltipInterpolator(config.interpolateTooltip);
if (vizOrientation.xOri === ScaleOrientation.Horizontal && xTickLabelRotation !== 0) {
builder.setPadding(getRotationPadding(frame, xTickLabelRotation, xTickLabelMaxLength));
if (xTickLabelRotation !== 0) {
// these are the amount of space we already have available between plot edge and first label
// TODO: removing these hardcoded value requires reading back uplot instance props
let lftSpace = 50;
let btmSpace = vizOrientation.xOri === ScaleOrientation.Horizontal ? 14 : 5;
builder.setPadding(getRotationPadding(frame, xTickLabelRotation, xTickLabelMaxLength, lftSpace, btmSpace));
}
builder.setPrepData(config.prepData);
@ -155,12 +164,13 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
placement: xFieldAxisPlacement,
label: frame.fields[0].config.custom?.axisLabel,
splits: config.xSplits,
filter: vizOrientation.xOri === 0 ? config.hFilter : undefined,
values: config.xValues,
timeZone,
grid: { show: false },
ticks: { show: false },
gap: 15,
tickLabelRotation: xTickLabelRotation * -1,
tickLabelRotation: vizOrientation.xOri === 0 ? xTickLabelRotation * -1 : 0,
theme,
show: xFieldAxisShow,
});
@ -272,6 +282,8 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptionsEX> = ({
size: customConfig.axisWidth,
placement,
formatValue: (v, decimals) => formattedValueToString(field.display!(v, decimals)),
filter: vizOrientation.yOri === 0 ? config.hFilter : undefined,
tickLabelRotation: vizOrientation.xOri === 1 ? xTickLabelRotation * -1 : 0,
theme,
grid: { show: customConfig.axisGridShow },
});
@ -293,7 +305,13 @@ function shortenValue(value: string, length: number) {
}
}
function getRotationPadding(frame: DataFrame, rotateLabel: number, valueMaxLength: number): Padding {
function getRotationPadding(
frame: DataFrame,
rotateLabel: number,
valueMaxLength: number,
lftSpace = 0,
btmSpace = 0
): Padding {
const values = frame.fields[0].values;
const fontSize = UPLOT_AXIS_FONT_SIZE;
const displayProcessor = frame.fields[0].display ?? ((v) => v);
@ -325,9 +343,15 @@ function getRotationPadding(frame: DataFrame, rotateLabel: number, valueMaxLengt
: 0;
// Add padding to the bottom to avoid clipping the rotated labels.
const paddingBottom = Math.sin(((rotateLabel >= 0 ? rotateLabel : rotateLabel * -1) * Math.PI) / 180) * maxLength;
const paddingBottom =
Math.sin(((rotateLabel >= 0 ? rotateLabel : rotateLabel * -1) * Math.PI) / 180) * maxLength - btmSpace;
return [Math.round(UPLOT_AXIS_FONT_SIZE * uPlot.pxRatio), paddingRight, paddingBottom, paddingLeft];
return [
Math.round(UPLOT_AXIS_FONT_SIZE * uPlot.pxRatio),
paddingRight,
paddingBottom,
Math.max(0, paddingLeft - lftSpace),
];
}
/** @internal */