Tldraw/packages/tldraw/src/lib/shapes/shared/getPerfectDashProps.ts

98 wiersze
2.0 KiB
TypeScript

import { TLDefaultDashStyle } from '@tldraw/editor'
/** @public */
export function getPerfectDashProps(
totalLength: number,
strokeWidth: number,
opts = {} as Partial<{
style: TLDefaultDashStyle
snap: number
end: 'skip' | 'outset' | 'none'
start: 'skip' | 'outset' | 'none'
lengthRatio: number
closed: boolean
}>
): {
strokeDasharray: string
strokeDashoffset: string
} {
const {
closed = false,
snap = 1,
start = 'outset',
end = 'outset',
lengthRatio = 2,
style = 'dashed',
} = opts
let dashLength = 0
let dashCount = 0
let ratio = 1
let gapLength = 0
let strokeDashoffset = 0
switch (style) {
case 'dashed': {
ratio = 1
dashLength = Math.min(strokeWidth * lengthRatio, totalLength / 4)
break
}
case 'dotted': {
ratio = 100
dashLength = strokeWidth / ratio
break
}
default: {
return {
strokeDasharray: 'none',
strokeDashoffset: 'none',
}
}
}
if (!closed) {
if (start === 'outset') {
totalLength += dashLength / 2
strokeDashoffset += dashLength / 2
} else if (start === 'skip') {
totalLength -= dashLength
strokeDashoffset -= dashLength
}
if (end === 'outset') {
totalLength += dashLength / 2
} else if (end === 'skip') {
totalLength -= dashLength
}
}
dashCount = Math.floor(totalLength / dashLength / (2 * ratio))
dashCount -= dashCount % snap
if (dashCount < 3 && style === 'dashed') {
if (totalLength / strokeWidth < 5) {
dashLength = totalLength
dashCount = 1
gapLength = 0
} else {
dashLength = totalLength * 0.333
gapLength = totalLength * 0.333
}
} else {
dashCount = Math.max(dashCount, 3)
dashLength = totalLength / dashCount / (2 * ratio)
if (closed) {
strokeDashoffset = dashLength / 2
gapLength = (totalLength - dashCount * dashLength) / dashCount
} else {
gapLength = (totalLength - dashCount * dashLength) / Math.max(1, dashCount - 1)
}
}
return {
strokeDasharray: [dashLength, gapLength].join(' '),
strokeDashoffset: strokeDashoffset.toString(),
}
}