Skip to content

Instantly share code, notes, and snippets.

@Pamblam
Created February 5, 2024 19:51
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 Pamblam/fb82360117fff23e7aa46f284fb9eeb4 to your computer and use it in GitHub Desktop.
Save Pamblam/fb82360117fff23e7aa46f284fb9eeb4 to your computer and use it in GitHub Desktop.
reusable javascript css animation function demo
<!DOCTYPE html>
<html>
<head>
<title>aminate</title>
</head>
<body>
<img id='img' src="https://static-00.iconduck.com/assets.00/heart-emoji-2048x1891-k5awv4hw.png"
style="position:absolute; left:0; top:0; width: 50px;" />
<script>
showHeartAnimation();
async function showHeartAnimation(){
let {ele, start_value, end_value} = await initImage(`https://static-00.iconduck.com/assets.00/heart-emoji-2048x1891-k5awv4hw.png`)
await runTimeline([
{at: 0, do:()=>animate(ele, 'top', start_value, end_value, 'px', 1500)},
{at: 0, do:()=>animate(ele, 'transform', 0, 30, v=>`rotate(${v}deg)`, 500)},
{at: 500, do:()=>animate(ele, 'transform', 30, -30, v=>`rotate(${v}deg)`, 500)},
{at: 1000, do:()=>animate(ele, 'transform', -30, 0, v=>`rotate(${v}deg)`, 500)},
{at: 1250, do:()=>animate(ele, 'opacity', 1, 0, '', 250)},
]);
ele.remove();
async function initImage(src){
let img = await loadImg(`https://static-00.iconduck.com/assets.00/heart-emoji-2048x1891-k5awv4hw.png`);
let vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
let vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
document.body.appendChild(img);
img.style.maxWidth = `${vw * .8}px`;
img.style.maxHeight = `${vh * .8}px`;
let ibb = img.getBoundingClientRect();
let iw = ibb.width;
let ih = ibb.height;
img.style.position = 'fixed';
img.style.top = `${vh}px`;
img.style.left = `${(vw / 2) - (iw / 2)}px`;
return {ele:img, start_value:vh, end_value:(vh / 2) - (ih / 2)};
}
}
async function runTimeline(animations){
let promises = animations.map(ani=>{
return new Promise(d=>{
setTimeout(()=>ani.do().then(d), ani.at)
})
});
await Promise.all(promises);
}
function wait(ms) {
return new Promise(done => {
setTimeout(() => done(), ms);
});
}
function loadImg(src) {
return new Promise(done => {
let img = new Image();
img.onload = () => done(img);
img.onerror = () => console.log('nopr');
img.src = src;
});
}
function animate(element, style_property, start_value, end_value, unit, duration) {
return new Promise((resolve, reject) => {
let start_time = Date.now();
let diff = Math.abs(start_value - end_value);
(function frame() {
requestAnimationFrame(() => {
let time_passed = Date.now() - start_time;
let percent = time_passed / duration;
let position_change = diff * percent;
let position;
if (start_value > end_value) {
position = Math.max(start_value - position_change, end_value);
} else {
position = Math.min(start_value + position_change, end_value);
}
let value;
if('function' === typeof unit){
value = unit(position);
}else{
value = `${position}${unit}`;
}
element.style[style_property] = value;
if (position == end_value) resolve();
else frame();
});
})();
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment