-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add class property, angles in degree, fix styles
- Loading branch information
Showing
3 changed files
with
130 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,55 @@ | ||
// Clamp value between min and max | ||
export const clamp = (val: number, minVal: number, maxVal: number) => | ||
Math.max(minVal, Math.min(maxVal, val)); | ||
export const clamp = (value: number, min: number, max: number): number => | ||
Math.max(min, Math.min(max, value)); | ||
|
||
// Map value to an angle (in radians) | ||
export const valueToAngle = (value: number, min: number, max: number, startAngle: number, stopAngle: number) => | ||
startAngle + (stopAngle - startAngle) * (clamp(value, min, max) - min) / (max - min); | ||
// Scale value | ||
export const scale = (value: number, start: number, stop: number, targetStart: number, targetStop: number): number => | ||
targetStart + (targetStop - targetStart) * (clamp(value, start, stop) - start) / (stop - start); | ||
|
||
// Calculate title offset based on index and total count | ||
export const getTitleOffset = (startAngle: number, stopAngle: number, index: number, count: number): number => { | ||
const fullCircle = 360; | ||
const isCircleGauge = Math.abs(stopAngle - startAngle - fullCircle) < 0.001; | ||
const normalizedIndex = index / (count - (isCircleGauge || count === 1 ? 0 : 1)); | ||
const angle = normalizedIndex * fullCircle; | ||
|
||
// Offset calculation based on proportional angle | ||
return Math.abs(25 + (50 * angle) / fullCircle); | ||
}; | ||
|
||
export const getTitleAngle = (startAngle: number, stopAngle: number, index: number, count: number) => { | ||
const isCircleGauge = Math.abs(Math.abs(stopAngle - startAngle) - 2 * Math.PI) < 0.001; | ||
return startAngle + (index / (count - (isCircleGauge ? 0 : 1))) * (stopAngle - startAngle) | ||
} | ||
// Convert polar coordinates to Cartesian | ||
export const polarToCartesian = (radius: number, offset: number, angle: number) => { | ||
export const polarToCartesian = (radius: number, offset: number, angle: number): { x: string; y: string } => { | ||
const adjustedRadius = radius - offset; | ||
return { | ||
x: (radius - adjustedRadius * Math.sin(angle)).toFixed(2), | ||
y: (radius + adjustedRadius * Math.cos(angle)).toFixed(2), | ||
x: (radius - adjustedRadius * Math.sin(angle)).toFixed(3), | ||
y: (radius + adjustedRadius * Math.cos(angle)).toFixed(3), | ||
}; | ||
}; | ||
|
||
// Generate SVG path for an arc | ||
export const calcCurvePath = ( | ||
radius: number, | ||
offset: number, | ||
startAngle: number, | ||
stopAngle: number | ||
) => { | ||
if (stopAngle - startAngle >= 2 * Math.PI) | ||
stopAngle = startAngle + 2 * Math.PI - 0.0001; | ||
const start = polarToCartesian(radius, offset, startAngle); | ||
const end = polarToCartesian(radius, offset, stopAngle); | ||
const largeArc = stopAngle - startAngle > Math.PI ? 1 : 0; | ||
const sweepFlag = stopAngle > startAngle ? 1 : 0; | ||
return `M ${start.x} ${start.y} A | ||
${radius - offset} ${radius - offset} | ||
0 ${largeArc} ${sweepFlag} ${end.x} ${end.y}`; | ||
}; | ||
export const calcCurvePath = (radius: number, offset: number, startAngle: number, endAngle: number): string => { | ||
const startRad = startAngle * Math.PI / 180; | ||
const endRad = endAngle * Math.PI / 180; | ||
|
||
const startPoint = polarToCartesian(radius, offset, startRad); | ||
|
||
// Helper to generate an arc command for SVG path | ||
const arcCommand = (fromAngle: number, toAngle: number): string => { | ||
toAngle = Math.min(toAngle, fromAngle + Math.PI * 1.9999) | ||
const endPoint = polarToCartesian(radius, offset, toAngle); | ||
const largeArcFlag = toAngle - fromAngle > Math.PI ? 1 : 0; | ||
const sweepFlag = toAngle > fromAngle ? 1 : 0; | ||
return `A ${radius - offset} ${radius - offset} 0 ${largeArcFlag} ${sweepFlag} ${endPoint.x} ${endPoint.y}`; | ||
}; | ||
|
||
// Determine whether to split into two arcs for full circles | ||
let cmd = `M ${startPoint.x} ${startPoint.y}`; | ||
let arcStart = startRad | ||
do { | ||
const arcStop = arcStart + Math.min(Math.PI * 2, endRad - arcStart) | ||
cmd += ` ${arcCommand(arcStart, arcStop)}`; | ||
arcStart = arcStop; | ||
} while (arcStart < endRad) | ||
|
||
return cmd; | ||
}; |