Skip to content

feat(morph-loader): add twelve more Material 3 expressive shapes - #50

Open
dennytosp wants to merge 1 commit into
rit3zh:mainfrom
dennytosp:feat/morph-loader-m3-shapes
Open

feat(morph-loader): add twelve more Material 3 expressive shapes#50
dennytosp wants to merge 1 commit into
rit3zh:mainfrom
dennytosp:feat/morph-loader-m3-shapes

Conversation

@dennytosp

@dennytosp dennytosp commented Aug 22, 2026

Copy link
Copy Markdown

Closes #43

Adds 6-sided-cookie, 9-sided-cookie, 12-sided-cookie, sunny, burst, clover-4, clover-8, flower, triangle, diamond, square and gem, taking SHAPES from 7 to 19.

Grey = already shipped, purple = new. Every shape below is rendered through the component's own pipeline (prepareShape → 80-point resample → straight-line polygon), so this is what the loader actually draws:

All 19 shapes rendered through the component pipeline

Notes

Written as SVG paths. prepareShape already accepts either a point list or a path string, and takes the SVG branch through flattenSvgPath. Authoring the new shapes as paths keeps them readable instead of adding ~600 numbers each, and lets Skia flatten them at exactly the resolution the loader samples.

Wound to match. All seven shipped shapes have a negative signed area and start near the top. Morphing interpolates point k of shape A to point k of shape B, so a shape wound the other way collapses through a degenerate midpoint. The new shapes follow the same convention — this was worth getting right, since it is invisible in a static render and only shows up mid-morph.

Defaults are unchanged. defaultShapes used to be Object.values({ ...SHAPES }), so adding any shape would have silently changed what an existing <MorphLoader /> renders. It now reads an explicit DEFAULT_SHAPE_KEYS list holding the original seven in their original order.

Verification

  • defaultShapes is byte-identical to main — an existing loader with no shapes prop cycles through exactly what it did before.
  • All 342 ordered shape pairs were interpolated at the midpoint: no NaN, and the worst area retention is 82.2% (4-sided-cookie → square). A mis-wound shape shows up here as a near-zero retention.
  • All 12 new shapes take the SVG-path branch of prepareShape; the 7 originals still take the point-list branch.
  • tsc --noEmit reports the same error count as main (none in these files).

Sample morphs, shipped → new:

Morph interpolation between shipped and new shapes

Open question

I kept the default rotation at the original seven so nothing changes for existing users. If you would rather the defaults cycle through more of the set, that is a one-line change to DEFAULT_SHAPE_KEYS — happy to adjust.

Adds `6-sided-cookie`, `9-sided-cookie`, `12-sided-cookie`, `sunny`,
`burst`, `clover-4`, `clover-8`, `flower`, `triangle`, `diamond`,
`square` and `gem` to `SHAPES`, taking the set from 7 to 19.

They are written as SVG path strings rather than point lists — the
existing `prepareShape` already accepts either — which keeps them
readable and lets Skia flatten them at the resolution the loader
actually samples.

Each new shape is wound the same way as the shipped ones and starts at
the top, so morphing between any pair interpolates point-for-point
instead of twisting through a collapsed midpoint.

`defaultShapes` now reads from an explicit `DEFAULT_SHAPE_KEYS` list
rather than every key in `SHAPES`, so a loader with no `shapes` prop
cycles through exactly what it did before.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add More shapes to morphing loader

1 participant