A clip that changes shape

A photo opens from a point into a diamond and then fills the frame, and afterwards a star-shaped badge rounds into a disc. The live example runs the badge alone, and the photo's code follows it.

<div id="stage" data-composition-id="reveal"     data-start="0" data-duration="3" data-width="1280" data-height="720" data-fps="30">
    <div class="layer" data-component="reveal" data-start="0" data-duration="3">
        <div class="layer badge" data-bind-style="badge"></div>
    </div>
</div>
const { scene, shape, matchPaths } = wildflower.kinetic;

const [STAR, DISC] = matchPaths([
    'path("' + shape('star', { points: 5, outer: 200, inner: 90, cx: 640, cy: 360 }) + '")',
    'path("' + shape('sector', { radius: 260, to: 360, cx: 640, cy: 360 }) + '")',
]);

scene('reveal', {
    keyframes: {
        badge: { clipPath: { at: [1.4, 2.6], to: [STAR, DISC], ease: 'power2.inOut' } },
    },
});
html, body { margin: 0; background: #0a0b10; }

#stage { position: relative; overflow: hidden; background: #14122a; }

.layer { position: absolute; inset: 0; }

.badge { background: #f5c542; }

[data-composition-id]:not([data-kinetic-ready]) { visibility: hidden; }
A clip that changes shape

  • A clipPath track over polygon() moves every vertex, so each keyframe lists the same number of points. The photo's first keyframe puts all four on the center.
  • A clipPath track over path("…") reads the path data inside the quotes as commands and numbers, so its keyframes need the same commands. The badge's star and disc go through matchPaths(), which takes path("…") values and returns them in the same form.
  • The coordinates inside path() are pixels in the element's own box, and every keyframe uses the same quote style, since the quotes are text.

The photo is a layer before the badge, and its track goes beside the badge's in the keyframes.

<div class="layer photo" data-bind-style="photo"></div>
.photo { background: url('harbour.jpg') center / cover; }
photo: {
    clipPath: {
        at: [0, 0.6, 1.4],
        to: ['polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)', 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)', 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)'],
        ease: ['power2.out', 'power2.inOut'],
    },
},