<div class="animated-clip">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="animated-clip__svg">
<defs>
<clipPath id="octagon-clip" clipPathUnits="objectBoundingBox">
<path class="clip-path" d="M.5,1A.039.039,0,0,1,.4664.9809C.4078.8825.36.8459.2881.8459A.37663.37663,0,0,0,.1849.8635.0391.0391,0,0,1,.1365.8151.24521.24521,0,0,0,.1427.6506.27432.27432,0,0,0,.0191.5336a.03911.03911,0,0,1,0-.0672A.27226.27226,0,0,0,.1427.3494.24586.24586,0,0,0,.1365.1849.0391.0391,0,0,1,.1849.1365.37663.37663,0,0,0,.2881.1541c.0714,0,.12-.0366.1783-.135a.0391.0391,0,0,1,.0672,0c.0586.0984.1069.135.1783.135A.37663.37663,0,0,0,.8151.1365.0391.0391,0,0,1,.8635.1849.24521.24521,0,0,0,.8573.3494a.27432.27432,0,0,0,.1236.117.0391.0391,0,0,1,0,.0672.27481.27481,0,0,0-.1236.117A.24359.24359,0,0,0,.8629.8133.038.038,0,0,1,.865.8259.0391.0391,0,0,1,.8267.865.03856.03856,0,0,1,.8151.8635.37663.37663,0,0,0,.7119.8459c-.0714,0-.12.0366-.1783.135A.039.039,0,0,1,.5,1Z"/>
</clipPath>
</defs>
<g clip-path="url(#octagon-clip)">
<image height="100" width="100" preserveAspectRatio="xMidYMid slice" href="https://images.unsplash.com/photo-1506891536236-3e07892564b7?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDd8fHxlbnwwfHx8&auto=format&fit=crop&w=334&q=80"></image>
<image class="top-image" height="100" width="100" preserveAspectRatio="xMidYMid slice" href="https://images.unsplash.com/photo-1526336024174-e58f5cdd8e13?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80"></image>
</g>
</svg>
</div>
<div class="animated-clip">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="animated-clip__svg">
<defs>
<clipPath id="stairs-clip" clipPathUnits="objectBoundingBox">
<path class="clip-path" d="M1 1H0V0.549819H0.137003V0.274909H0.26827V0H1V1Z"/>
</clipPath>
</defs>
<g clip-path="url(#stairs-clip)">
<image height="100" width="100" preserveAspectRatio="xMidYMid slice" href="https://images.unsplash.com/photo-1506891536236-3e07892564b7?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDd8fHxlbnwwfHx8&auto=format&fit=crop&w=334&q=80"></image>
<image class="top-image" height="100" width="100" preserveAspectRatio="xMidYMid slice" href="https://images.unsplash.com/photo-1526336024174-e58f5cdd8e13?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80"></image>
</g>
</svg>
</div>
.animated-clip {
display: inline-block;
width: 220px;
}
.animated-clip__svg {
display: block;
width: 220px;
}
const svgEls = document.querySelectorAll('.animated-clip__svg');
createAnimation(svgEls[0], {
from: { rotate: 0 },
to: { rotate: 360 },
duration: 10e3,
easing: 'linear',
loop: true,
}, {
from: { scale: 0.5 },
to: { scale: 0.8 },
duration: 2000,
// easing: 'linear',
}, {
from: { opacity: 1 },
to: { opacity: 0 },
duration: 1200,
easing: 'linear',
});
createAnimation(svgEls[1], {
from: { rotate: -15 },
to: { rotate: 15 },
duration: 2e3,
easing: 'linear',
loop: true,
direction: 'alternate',
}, {
from: { scale: 0.5 },
to: { scale: 0.8 },
duration: 2000,
// easing: 'linear',
}, {
from: { opacity: 1 },
to: { opacity: 0 },
duration: 1000,
easing: 'linear',
});
function createAnimation(svg, animProp, clipProp, imageProp) {
const clipEl = svg.querySelector('.clip-path');
const imageEl = svg.querySelector('.top-image');
const { from: animFrom, to: animTo, animOpts } = animProp;
const { from: clipFrom, to: clipTo, clipOpts } = clipProp;
const { from: imageFrom, to: imageTo, imageOpts } = imageProp;
const animProps = { animFrom, clipFrom, imageFrom };
animOpts.targets = clipOpts.targets = imageOpts.targets = animProps;
const render = (anim) => {
const transformValue = `
translate(0.5 0.5)
scale(${animProps.scale})
rotate(${animProps.rotate})
translate(-0.5 -0.5)
`;
clipEl.setAttribute('transform', transformValue);
imageEl.setAttribute('opacity', animProps.opacity);
};
animOpts.update = clipOpts.update = imageOpts.update = render;
anime({animTo, animOpts});
svg.addEventListener('mouseenter', () => {
anime({clipTo, clipOpts});
anime({imageTo, imageOpts});
});
svg.addEventListener('mouseleave', () => {
anime({clipFrom, clipOpts});
anime({imageFrom, imageOpts});
});
}
This Pen doesn't use any external CSS resources.