kopia lustrzana https://github.com/Tldraw/Tldraw
136 wiersze
3.4 KiB
TypeScript
136 wiersze
3.4 KiB
TypeScript
import {
|
|
TLDefaultColorTheme,
|
|
TLGeoShape,
|
|
TLShapeId,
|
|
Vec,
|
|
canonicalizeRotation,
|
|
} from '@tldraw/editor'
|
|
import * as React from 'react'
|
|
import {
|
|
ShapeFill,
|
|
getShapeFillSvg,
|
|
getSvgWithShapeFill,
|
|
useDefaultColorTheme,
|
|
} from '../../shared/ShapeFill'
|
|
import { getPerfectDashProps } from '../../shared/getPerfectDashProps'
|
|
import { cloudSvgPath, getCloudArcs } from '../cloudOutline'
|
|
|
|
export const DashStyleCloud = React.memo(function DashStylePolygon({
|
|
dash,
|
|
fill,
|
|
color,
|
|
strokeWidth,
|
|
w,
|
|
h,
|
|
id,
|
|
size,
|
|
}: Pick<TLGeoShape['props'], 'dash' | 'fill' | 'color' | 'w' | 'h' | 'size'> & {
|
|
strokeWidth: number
|
|
id: TLShapeId
|
|
}) {
|
|
const theme = useDefaultColorTheme()
|
|
const innerPath = cloudSvgPath(w, h, id, size)
|
|
const arcs = getCloudArcs(w, h, id, size)
|
|
|
|
return (
|
|
<>
|
|
<ShapeFill theme={theme} d={innerPath} fill={fill} color={color} />
|
|
<g strokeWidth={strokeWidth} stroke={theme[color].solid} fill="none" pointerEvents="all">
|
|
{arcs.map(({ leftPoint, rightPoint, center, radius }, i) => {
|
|
const arcLength = center
|
|
? radius *
|
|
canonicalizeRotation(
|
|
canonicalizeRotation(Vec.Angle(center, rightPoint)) -
|
|
canonicalizeRotation(Vec.Angle(center, leftPoint))
|
|
)
|
|
: Vec.Dist(leftPoint, rightPoint)
|
|
|
|
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(
|
|
arcLength,
|
|
strokeWidth,
|
|
{
|
|
style: dash,
|
|
start: 'outset',
|
|
end: 'outset',
|
|
}
|
|
)
|
|
|
|
return (
|
|
<path
|
|
key={i}
|
|
d={
|
|
center
|
|
? `M${leftPoint.x},${leftPoint.y}A${radius},${radius},0,0,1,${rightPoint.x},${rightPoint.y}`
|
|
: `M${leftPoint.x},${leftPoint.y}L${rightPoint.x},${rightPoint.y}`
|
|
}
|
|
strokeDasharray={strokeDasharray}
|
|
strokeDashoffset={strokeDashoffset}
|
|
/>
|
|
)
|
|
})}
|
|
</g>
|
|
</>
|
|
)
|
|
})
|
|
|
|
export function DashStyleCloudSvg({
|
|
dash,
|
|
fill,
|
|
color,
|
|
theme,
|
|
strokeWidth,
|
|
w,
|
|
h,
|
|
id,
|
|
size,
|
|
}: Pick<TLGeoShape['props'], 'dash' | 'fill' | 'color' | 'w' | 'h' | 'size'> & {
|
|
id: TLShapeId
|
|
strokeWidth: number
|
|
theme: TLDefaultColorTheme
|
|
}) {
|
|
const innerPath = cloudSvgPath(w, h, id, size)
|
|
const arcs = getCloudArcs(w, h, id, size)
|
|
|
|
const strokeElement = document.createElementNS('http://www.w3.org/2000/svg', 'g')
|
|
strokeElement.setAttribute('stroke-width', strokeWidth.toString())
|
|
strokeElement.setAttribute('stroke', theme[color].solid)
|
|
strokeElement.setAttribute('fill', 'none')
|
|
|
|
for (const { leftPoint, rightPoint, center, radius } of arcs) {
|
|
const arcLength = center
|
|
? radius *
|
|
canonicalizeRotation(
|
|
canonicalizeRotation(Vec.Angle(center, rightPoint)) -
|
|
canonicalizeRotation(Vec.Angle(center, leftPoint))
|
|
)
|
|
: Vec.Dist(leftPoint, rightPoint)
|
|
|
|
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(arcLength, strokeWidth, {
|
|
style: dash,
|
|
start: 'outset',
|
|
end: 'outset',
|
|
})
|
|
|
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
path.setAttribute(
|
|
'd',
|
|
center
|
|
? `M${leftPoint.x},${leftPoint.y}A${radius},${radius},0,0,1,${rightPoint.x},${rightPoint.y}`
|
|
: `M${leftPoint.x},${leftPoint.y}L${rightPoint.x},${rightPoint.y}`
|
|
)
|
|
path.setAttribute('stroke-dasharray', strokeDasharray.toString())
|
|
path.setAttribute('stroke-dashoffset', strokeDashoffset.toString())
|
|
strokeElement.appendChild(path)
|
|
}
|
|
|
|
// Get the fill element, if any
|
|
const fillElement = getShapeFillSvg({
|
|
d: innerPath,
|
|
fill,
|
|
color,
|
|
theme,
|
|
})
|
|
|
|
return getSvgWithShapeFill(strokeElement, fillElement)
|
|
}
|