Fix VO2 arrow: tip lands at exact value on arc centre-line, base points outward
Previously the tip was sitting just outside the outer edge of the track, making it hard to see exactly where it pointed. Now tipR=r (centre of the coloured band) so the tip is precisely at the value's position, with a narrow 5° spread for better precision. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -89,13 +89,13 @@ function Vo2MaxGauge({ value, birthYear, biologicalSex }) {
|
|||||||
|
|
||||||
const cat = value != null ? getVo2Category(value, age, biologicalSex) : null
|
const cat = value != null ? getVo2Category(value, age, biologicalSex) : null
|
||||||
|
|
||||||
// Small white triangle: base outside the arc, tip touching the outer edge — points inward
|
// White arrow: tip lands exactly at the arc centre-line at the value's angle;
|
||||||
|
// base extends outside the track — unambiguously marks the precise position.
|
||||||
const arrowPts = value != null ? (() => {
|
const arrowPts = value != null ? (() => {
|
||||||
const a = toAngle(Math.max(MIN, Math.min(MAX, value)))
|
const a = toAngle(Math.max(MIN, Math.min(MAX, value)))
|
||||||
const outerEdge = r + sw / 2 // outer surface of the track
|
const tipR = r // tip at centre of the coloured track
|
||||||
const tipR = outerEdge + 1 // tip just outside the track surface
|
const baseR = r + sw / 2 + 9 // base well outside the outer edge
|
||||||
const baseR = outerEdge + 12 // base further out
|
const s = 0.09 // half-spread ≈ 5° — narrow for precision
|
||||||
const s = 0.11 // half-spread ≈ 6°
|
|
||||||
const tipX = cx + tipR * Math.cos(a), tipY = cy - tipR * Math.sin(a)
|
const tipX = cx + tipR * Math.cos(a), tipY = cy - tipR * Math.sin(a)
|
||||||
const b1x = cx + baseR * Math.cos(a + s), b1y = cy - baseR * Math.sin(a + s)
|
const b1x = cx + baseR * Math.cos(a + s), b1y = cy - baseR * Math.sin(a + s)
|
||||||
const b2x = cx + baseR * Math.cos(a - s), b2y = cy - baseR * Math.sin(a - s)
|
const b2x = cx + baseR * Math.cos(a - s), b2y = cy - baseR * Math.sin(a - s)
|
||||||
@@ -104,7 +104,6 @@ function Vo2MaxGauge({ value, birthYear, biologicalSex }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
{/* Extra top padding so the arrow doesn't clip at the top of the card */}
|
|
||||||
<svg width="140" height="92" viewBox="0 0 140 92">
|
<svg width="140" height="92" viewBox="0 0 140 92">
|
||||||
{/* Dark background track, slightly wider than the colour bands */}
|
{/* Dark background track, slightly wider than the colour bands */}
|
||||||
<path d={arc(MIN, MAX)} stroke="#1f2937" strokeWidth={sw + 4} fill="none" strokeLinecap="butt" />
|
<path d={arc(MIN, MAX)} stroke="#1f2937" strokeWidth={sw + 4} fill="none" strokeLinecap="butt" />
|
||||||
@@ -120,7 +119,7 @@ function Vo2MaxGauge({ value, birthYear, biologicalSex }) {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{/* White arrow pointing inward at the value's position */}
|
{/* White arrow: tip at exact value position on arc, base pointing outward */}
|
||||||
{arrowPts && <polygon points={arrowPts} fill="white" />}
|
{arrowPts && <polygon points={arrowPts} fill="white" />}
|
||||||
|
|
||||||
{/* VO2 number, coloured by category */}
|
{/* VO2 number, coloured by category */}
|
||||||
|
|||||||
Reference in New Issue
Block a user