<div class="container">
<div class="morph-img">
<svg class="img-svg" width="500" height="500" viewBox="0 0 500 500">
<defs>
<clipPath id="clipShape">
<path class="svg-path"
d="M 378.1,121.2 C 408.4,150 417.2,197.9 411,245.8 404.8,293.7 383.5,341.7 353.4,370.7 303.2,419.1 198.7,427.7 144.5,383.8 86.18,336.5 67.13,221.3 111.9,161 138.6,125 188.9,99.62 240.7,90.92 292.4,82.24 345.6,90.32 378.1,121.2 Z"
/>
</clipPath>
</defs>
<g clip-path="url(#clipShape)">
<image class="img1 img" href="https://picsum.photos/500/500?random=1" />
<image class="img2 img" href="https://picsum.photos/500/500?random=2" />
<image class="img3 img" href="https://picsum.photos/500/500?random=3" />
<image class="img4 img" href="https://picsum.photos/500/500?random=4" />
</g>
</svg>
</div>
</div>
* {
margin: 0;
padding: 0;
}
body {
background: #eee;
overflow: hidden;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.img {
opacity: 0;
transition: opacity 1.5s ease-in;
}
.morph-img {
width: 350px;
}
svg {
width: 100%;
}
class SVGMorphing {
constructor() {
this.el = document.querySelector('.morph-img');
if(!this.el) return
this.init();
}
init() {
const paths = [
'M 378.1,121.2 C 408.4,150 417.2,197.9 411,245.8 404.8,293.7 383.5,341.7 353.4,370.7 303.2,419.1 198.7,427.7 144.5,383.8 86.18,336.5 67.13,221.3 111.9,161 138.6,125 188.9,99.62 240.7,90.92 292.4,82.24 345.6,90.32 378.1,121.2 Z',
'M 418.1,159.8 C 460.9,222.9 497,321.5 452.4,383.4 417.2,432.4 371.2,405.6 271.3,420.3 137.2,440 90.45,500.6 42.16,442.8 -9.572000000000003,381 86.33,289.1 117.7,215.5 144.3,153.4 145.7,54.21 212.7,36.25 290.3,15.36 373.9,94.6 418.1,159.8 Z',
'M 451.5,185.8 C 441.5,266.2 339.6,305 272.3,350.2 207.7,393.6 226.7,444.7 182.6,447.9 132.8,451.4 83.97,399.9 66.37,353.1 34.6,268.4 41.16,141.8 112,85.44 186.1,26.33 313.8,54.1 396,101.4 425.2,118.2 455.6,152.4 451.5,185.8 Z',
'M 368.1,46.41999999999999 C 461,96.69 473.7,266.2 422.3,358.4 379.1,436 259.6,484.8 175,457.5 107.5,435.7 12.650000000000006,329.8 60.93,277.7 95.18,240.8 154,379.3 194.2,348.9 250.7,306 116,204.1 148.4,140.9 184.8,70.02 298,8.455000000000013 368.1,46.41999999999999 Z',
];
this.svgPath = this.el.querySelector('.svg-path');
this.images = this.el.querySelectorAll('.img');
this.animation(paths);
}
animation(paths) {
const tl = gsap.timeline({
repeat: -1,
defaults: { duration: 2.8, ease: "elastic.inOut",},
});
paths.forEach((path, index) => {
const nextIndex = (index + 1) % paths.length;
tl.to(this.svgPath, {
attr: { d: paths[nextIndex] },
onStart: () => {
this.images[index].style.opacity = 1;
},
onComplete: () => {
this.images[index].style.opacity = 0;
}
});
});
}
}
new SVGMorphing();
This Pen doesn't use any external CSS resources.