Skip to content

Instantly share code, notes, and snippets.

@arnoson
Last active November 8, 2021 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnoson/8eaf93f7d96e412e3db8b0ef250533a4 to your computer and use it in GitHub Desktop.
Save arnoson/8eaf93f7d96e412e3db8b0ef250533a4 to your computer and use it in GitHub Desktop.
Stretch a round paper.js path item
const getBottomSegment = (segments) =>
segments.reduce((prev, curr) => (curr.point.y > prev.point.y ? curr : prev))
const getTopSegment = (segments) =>
segments.reduce((prev, curr) => (curr.point.y < prev.point.y ? curr : prev))
const wrapSegmentIndex = (path, index) =>
(index =
index < 0 ? path.segments.length + index : index % path.segments.length)
const moveSegments = (path, startSegment, endSegment, deltaX) => {
startIndex = wrapSegmentIndex(path, startSegment.index)
endIndex = wrapSegmentIndex(path, endSegment.index)
if (startIndex > endIndex) {
;[startIndex, endIndex] = [endIndex, startIndex]
}
for (let i = startIndex; i <= endIndex; i++) {
path.segments[i].point.x += deltaX
}
}
const stretch = (path, scale, options = {}) => {
const { width, height } = path.bounds
const widthDifference = width * scale - width
const topSegment = options.topSegment ?? getTopSegment(path.segments)
const bottomSegment = options.bottomSegment ?? getBottomSegment(path.segments)
moveSegments(
path,
topSegment.next,
bottomSegment.previous,
widthDifference / 2
)
moveSegments(
path,
bottomSegment.next,
topSegment.previous,
(widthDifference / 2) * -1
)
const topPartHeight = Math.abs(
topSegment.point.y -
getBottomSegment([topSegment.next, topSegment.previous]).point.y
)
const bottomPartHeight = Math.abs(
bottomSegment.point.y -
getTopSegment([bottomSegment.next, bottomSegment.previous]).point.y
)
const heightWeight = options.heightWeight ?? 0.3
const transitionWeight = options.transitionWeight ?? 0.8
const transitionHandleStretch = scale * transitionWeight + (1 - transitionWeight)
topSegment.handleIn.length *= scale
topSegment.handleOut.length *= scale
topSegment.point.y -= (scale - 1) * topPartHeight * heightWeight
bottomSegment.handleIn.length *= scale
bottomSegment.handleOut.length *= scale
bottomSegment.point.y += (scale - 1) * bottomPartHeight * heightWeight
topSegment.previous.handleOut.length *= transitionHandleStretch
topSegment.next.handleIn.length *= transitionHandleStretch
bottomSegment.previous.handleOut.length *= transitionHandleStretch
bottomSegment.next.handleIn.length *= transitionHandleStretch
}
const svg =
project.importSVG(`<svg width="511" height="313" viewBox="0 0 511 313" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M410.554 64.754C410.554 80.5157 392.702 94.962 363.029 106.191C417.821 117.818 453.868 137.56 453.868 159.957C453.868 172.784 442.045 184.739 421.65 194.799C475.605 206.466 511 226.052 511 248.246C511 284.009 419.094 313 305.723 313C192.352 313 100.446 284.009 100.446 248.246C100.446 235.419 112.269 223.464 132.664 213.404C78.7091 201.737 43.3141 182.151 43.3141 159.957C43.3141 144.195 61.1659 129.749 90.8394 118.52C36.0474 106.893 0 87.1513 0 64.754C0 28.9914 91.9056 0 205.277 0C318.648 0 410.554 28.9914 410.554 64.754Z" fill="#C4C4C4"/>
</svg>
`)
svg.firstChild.remove()
svg.position = view.center
const path = svg.firstChild
stretch(path, 1.5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment