I've seen a number of examples of jQuery plugins that create slideshows with lots of different styles of effects when the images transition from one to another.
I have been playing with this over the last day or so, and have some nice working examples of a slideshow using JQuery and would like start to use some of the more exotic transitions rather than simple sliding images in a list from left to right, or fading one image out and another in.
I want to lean how to do this myself, rather than use plugins, and wondered if anyone has an simple example of how I would transition from one image to another and have a block effect (or other other fancy effects), where one image is replaced by another made up of smaller blocks that fade in etc?
Thanks
Here's a way using vanilla JS, and the Animation API
background-image
with the respective background-position// Utility functions:
const el = (sel, par = document) => par.querySelector(sel);
const els = (sel, par = document) => par.querySelectorAll(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
const repeat = (n, cb) => [...Array(n)].forEach((_, i) => cb(i));
// Cut Gallery
const cuts = 8;
const elGallery = el('#gallery');
const images = [
"https://picsum.photos/id/40/600/400",
"https://picsum.photos/id/36/600/400",
"https://picsum.photos/id/39/600/400",
"https://picsum.photos/id/133/600/400",
"https://picsum.photos/id/120/600/400"
];
const tot = images.length;
let canAnimate = true;
let curr = 0;
// Preload images
images.forEach((src) => {
const img = new Image();
img.src = src;
});
// Creates a new set of 5 DIV:
const createSlides = () => {
elGallery.innerHTML = "";
repeat(cuts, (i) => {
const pct = 100 / (cuts - 1) * i;
const div = elNew("div", {
className: "slide",
style: `background: no-repeat url(${images[curr]}) ${pct}% center / ${cuts * 100}% auto;`
});
elGallery.append(div);
})
};
const getAnimation = (index, i) => {
const fxs = [
[{ translate: `0% -100%` }],
[{ translate: `0% 100%` }],
[{ translate: `${-100 * (i + 1)}% 0%`}],
[{ translate: `${100 * (cuts - i)}% 0%` }],
[{ opacity: 0, scale: 1.2 }],
[{ rotate: "45deg", opacity: 0, translate: "0 -100%" }],
];
return fxs[index];
};
let totAnimations = 6;
let currentAnimation = 0;
const anim = () => {
canAnimate = false;
elGallery.style.backgroundImage = `url(${images[curr]})`;
els(".slide", elGallery).forEach((elSlide, i) => {
elSlide.animate(getAnimation(currentAnimation, i), {
duration: 500,
delay: i * 80,
fill: "forwards",
easing: "cubic-bezier(0.5, 0, 1, 0.7)"
}).addEventListener("finish", () => {
if (i < cuts - 1) return;
createSlides();
canAnimate = true;
});
});
currentAnimation += 1;
currentAnimation %= totAnimations;
};
// INIT
createSlides();
el("#next").addEventListener("click", () => {
if (!canAnimate) return;
curr = ++curr % tot; // Increment counter
anim();
});
* { margin: 0; box-sizing: border-box; }
#gallery{
display: flex;
overflow: hidden;
height: 200px;
background: no-repeat center / 100%;
& .slide {
position: relative;
flex: 1;
}
}
<button id="next">Show next effect</button>
Click to see all random FX!
<div id="gallery"></div>