Skip to content

Instantly share code, notes, and snippets.

@steveruizok
Last active February 19, 2024 00:38
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steveruizok/7b30a30f915362f219d0516073f92d69 to your computer and use it in GitHub Desktop.
Save steveruizok/7b30a30f915362f219d0516073f92d69 to your computer and use it in GitHub Desktop.
Get balanced stroke dash array and stroke dash offset for an ellipse.

Demo

https://codesandbox.io/s/dark-shadow-sxz3q

Examples

const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(
  200,
  10,
  'dotted'
)

const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(
  200,
  10,
  'dashed'
)

// Produce dashes in multiple of two.
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(
  200,
  10,
  'dashed',
  2
)


// Produce dashes in multiple of four.
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(
  200,
  10,
  'dashed',
  2
)
/**
* Get balanced dash-strokearray and dash-strokeoffset properties for a path of a given length.
* @param length The length of the path.
* @param strokeWidth The shape's stroke-width property.
* @param style The stroke's style: "dashed" or "dotted" (default "dashed").
* @param snap An interval for dashes (e.g. 4 will produce arrays with 4, 8, 16, etc dashes).
*/
export function getPerfectDashProps(
length: number,
strokeWidth: number,
style: 'dashed' | 'dotted' = 'dashed',
snap = 1
): {
strokeDasharray: string
strokeDashoffset: string
} {
let dashLength: number
let strokeDashoffset: string
let ratio: number
if (style === 'dashed') {
dashLength = strokeWidth * 2
ratio = 1
strokeDashoffset = (dashLength / 2).toString()
} else {
dashLength = strokeWidth / 100
ratio = 100
strokeDashoffset = '0'
}
let dashes = Math.floor(length / dashLength / (2 * ratio))
dashes -= dashes % snap
if (dashes === 0) dashes = 1
const gapLength = (length - dashes * dashLength) / dashes
return {
strokeDasharray: [dashLength, gapLength].join(' '),
strokeDashoffset,
}
}
@steveruizok
Copy link
Author

A useful helper when using this with circles or ellipses:

function getEllipsePerimeter(rx: number, ry: number) {
  const h = Math.pow(rx - ry, 2) / Math.pow(rx + ry, 2);
  return Math.PI * (rx + ry) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)));
}

@BuslikDrev
Copy link

Есть формулы получения сбалансированного штриха для четверти овала и круга?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment