diff --git a/src/components/charts/ordinal/GaugeChart.test.tsx b/src/components/charts/ordinal/GaugeChart.test.tsx index 34474c48..584e468a 100644 --- a/src/components/charts/ordinal/GaugeChart.test.tsx +++ b/src/components/charts/ordinal/GaugeChart.test.tsx @@ -471,7 +471,7 @@ describe("GaugeChart", () => { ) const band = (lastOrdinalFrameProps.data || []).find((d: Datum) => d._gradientBand) - expect(band?._gradientBand?.colors.length).toBeLessThanOrEqual(48) + expect(band?._gradientBand?.colors.length).toBeLessThanOrEqual(240) }) }) }) diff --git a/src/components/charts/ordinal/GaugeChart.tsx b/src/components/charts/ordinal/GaugeChart.tsx index 9168adc1..ee2c2a22 100644 --- a/src/components/charts/ordinal/GaugeChart.tsx +++ b/src/components/charts/ordinal/GaugeChart.tsx @@ -348,20 +348,60 @@ export const GaugeChart = forwardRef(function GaugeChart(props: GaugeChartProps, const labelPct = (ann.value - min) / range const startRad = -Math.PI / 2 + (startAngleDegFinal * Math.PI) / 180 const labelAngle = startRad + labelPct * sweepRad - const labelR = innerRadius - 14 const cx = (context.width || width) / 2 const cy = (context.height || height) / 2 + // Radial tick mark spanning the arc band — 1px past each edge so it + // reads as 2px wider than the arc total. + const markInner = innerRadius - 1 + const markOuter = radius + 1 + const mx1 = Math.cos(labelAngle) * markInner + const my1 = Math.sin(labelAngle) * markInner + const mx2 = Math.cos(labelAngle) * markOuter + const my2 = Math.sin(labelAngle) * markOuter + // Text sits outside the arc. Alignment follows the clock position + // of the mark: top sector (11–1) centered above, right sector (1–5) + // left-aligned, bottom sector (5–7) centered below, left sector + // (7–11) right-aligned. + const labelR = radius + 10 const lx = Math.cos(labelAngle) * labelR const ly = Math.sin(labelAngle) * labelR + // Clock hour from labelAngle: 12 at top, clockwise. + const hour = (((labelAngle + Math.PI / 2) / (2 * Math.PI)) * 12 + 12) % 12 + let textAnchor: "start" | "middle" | "end" = "middle" + let dominantBaseline: "auto" | "middle" | "hanging" = "middle" + if (hour >= 11 || hour < 1) { + textAnchor = "middle" + dominantBaseline = "auto" // text sits above the mark + } else if (hour >= 1 && hour < 5) { + textAnchor = "start" + dominantBaseline = "middle" + } else if (hour >= 5 && hour < 7) { + textAnchor = "middle" + dominantBaseline = "hanging" // text sits below the mark + } else { + textAnchor = "end" + dominantBaseline = "middle" + } return ( - - {ann.label} - + + + + {ann.label} + + ) } if (ann.type === "gauge-value") { diff --git a/src/components/charts/shared/gaugeGradient.ts b/src/components/charts/shared/gaugeGradient.ts index e8bd7b00..5a5781d0 100644 --- a/src/components/charts/shared/gaugeGradient.ts +++ b/src/components/charts/shared/gaugeGradient.ts @@ -140,7 +140,7 @@ export function buildGaugeArcModel(options: BuildGaugeArcModelOptions): GaugeArc fillZones, showScaleLabels, gradientFill, - gradientSteps = 48, + gradientSteps = 240, } = options const clampedValue = Math.max(min, Math.min(max, value))