Author: | Haja Randriakoto |
---|---|
Views Total: | 801 views |
Official Page: | Go to website |
Last Update: | March 1, 2021 |
License: | MIT |
Preview:

Description:
A pretty cool diagonal thumbnail carousel built using the Anime.js JavaScript library.
It takes a group of images and converts them into carousel UI where you can switch between thumbnails in the diagonal direction.
How to use it:
1. Insert your images into the thumbnail grids.
<div class="slider"> <div class="nav"> <div class="next"></div> <div class="prev"></div> <div class="explore-btn">Explore</div> </div> <div class="item is-active"> <div class="content"> <div class="wrap">Novitates</div> </div> <div class="imgs"> <div class="grid"> <div class="img img-1"><img src="1.jpg"/></div> <div class="img img-2"><img src="2.jpg"/></div> <div class="img img-3"><img src="3.jpg"/></div> <div class="img img-4"><img src="4.jpg"/></div> </div> </div> </div> <div class="item"> <div class="content"> <div class="wrap">Si spem</div> </div> <div class="imgs"> <div class="grid"> <div class="img img-1"><img src="1.jpg"/></div> <div class="img img-2"><img src="2.jpg"/></div> <div class="img img-3"><img src="3.jpg"/></div> <div class="img img-4"><img src="4.jpg"/></div> </div> </div> </div> <div class="item"> <div class="content"> <div class="wrap">Adferunt</div> </div> <div class="imgs"> <div class="grid"> <div class="img img-1"><img src="1.jpg"/></div> <div class="img img-2"><img src="2.jpg"/></div> <div class="img img-3"><img src="3.jpg"/></div> <div class="img img-4"><img src="4.jpg"/></div> </div> </div> </div> </div>
2. The necessary CSS styles for the diagonal carousel.
.slider { height: 100vh; width: 100vw; background-color: #0a0908; display: flex; align-items: center; justify-content: center; color: white; position: relative; overflow: hidden; transition: background-color 2s; } .slider .item .imgs { position: relative; width: 60%; padding-top: 60%; } .slider .item .imgs .grid { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: grid; grid-template-columns: repeat(12, 1fr); grid-template-rows: repeat(12, 1fr); grid-column-gap: 32px; grid-row-gap: 32px; transform: rotate(-20deg); opacity: 0.65; } .slider .item { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } .slider .item .img { width: 100%; height: 100%; position: relative; will-change: transform; will-change: opacity; } .slider .item .img img { position: absolute; top: 0; width: 100%; height: 100%; object-fit: cover; position: relative; -webkit-filter: contrast(110%) brightness(110%) saturate(130%); filter: contrast(110%) brightness(110%) saturate(130%); } .slider .item .img img::before { content: ""; display: block; height: 100%; width: 100%; top: 0; left: 0; position: absolute; pointer-events: none; mix-blend-mode: screen; background: rgba(243, 106, 188, 0.3); } .slider .item .img-1 { grid-area: 1/1/7/5; } .slider .item .img-2 { grid-area: 2/5/7/13; } .slider .item .img-3 { grid-area: 7/1/12/9; } .slider .item .img-4 { grid-area: 7/9/13/13; } .slider .item .content { position: absolute; z-index: 2; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; line-height: 1.15; font-size: 8rem; font-weight: 700; } .slider .item .content .wrap { text-align: center; text-shadow: 1px 1px 4px rgba(10, 9, 8, 0.2); width: 100%; max-width: 600px; line-height: 1; } .slider .item .content .wrap .letter { display: inline-block; } .slider .nav .next, .slider .nav .prev { height: 2rem; width: 2rem; position: absolute; top: calc(50% - 1rem); cursor: pointer; z-index: 3; transition: transform 0.3s; } .slider .nav .next { right: 2rem; background-image: url("data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M 19 8 L 19 11 L 1 11 L 1 13 L 19 13 L 19 16 L 23 12 L 19 8 z' fill='white'/%3E%3C/svg%3E"); } .slider .nav .next:hover { transform: translateX(0.5rem); } .slider .nav .prev { left: 2rem; background-image: url("data:image/svg+xml,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M 5 8 L 1 12 L 5 16 L 5 13 L 23 13 L 23 11 L 5 11 L 5 8 z' fill='white'/%3E%3C/svg%3E"); } .slider .nav .prev:hover { transform: translateX(-0.5rem); } .slider .nav .explore-btn { z-index: 4; position: absolute; bottom: 2rem; left: calc(50% - 4rem); width: 8em; text-align: center; padding: 1rem 0; border: solid 2px white; background: transparent; color: white; transition: background-color 0.3s; cursor: pointer; } .slider .nav .explore-btn:hover { color: #0a0908; background: white; } .slider .item:not(.is-active) { opacity: 0; pointer-events: none; }
3. Add the required anime.js JavaScript library to the page.
<script src="/path/to/cdn/anime.min.js"></script>
4. The main script to enable the diagonal carousel.
function init() {
const slider = document.querySelector(".slider");
const nextBtn = slider.querySelector(".slider .nav .next");
const prevBtn = slider.querySelector(".slider .nav .prev");
const items = slider.querySelectorAll(".slider .item");
let current = 0;
items.forEach(item => {
const textWrapper = item.querySelector(".wrap");
textWrapper.innerHTML = textWrapper.textContent.replace(
/\S/g,
"$&");
});
function anim(current, next, callback) {
const currentImgs = current.querySelectorAll(".img");
const currentText = current.querySelectorAll(".content .letter");
const nextImgs = next.querySelectorAll(".img");
const nextText = next.querySelectorAll(".content .letter");
const duration = 400;
const offset = "-=" + 300;
const imgOffset = duration * .8;
const tl = anime.timeline({
easing: "easeInOutQuint",
duration: duration,
complete: callback });
// Add children
tl.add({
targets: currentText,
translateY: [0, '-.75em'],
/*clipPath: ['polygon(0 0, 100% 0, 100% 100%, 0% 100%)', 'polygon(0 100%, 100% 100%, 100% 100%, 0% 100%)'],*/
opacity: [1, 0],
easing: "easeInQuint",
duration: 600,
delay: (el, i) => 10 * (i + 1) }).
add(
{
targets: currentImgs[0],
translateY: -600,
rotate: [0, '-15deg'],
opacity: [1, 0],
easing: "easeInCubic" },
offset).
add(
{
targets: currentImgs[1],
translateY: -600,
rotate: [0, '15deg'],
opacity: [1, 0],
easing: "easeInCubic" },
"-=" + imgOffset).
add(
{
targets: currentImgs[2],
translateY: -600,
rotate: [0, '-15deg'],
opacity: [1, 0],
easing: "easeInCubic" },
"-=" + imgOffset).
add(
{
targets: currentImgs[3],
translateY: -600,
rotate: [0, '15deg'],
opacity: [1, 0],
easing: "easeInCubic" },
"-=" + imgOffset).
add({
targets: current,
opacity: 0,
duration: 10,
easing: "easeInCubic" }).
add(
{
targets: next,
opacity: 1,
duration: 10 },
offset).
add(
{
targets: nextImgs[0],
translateY: [600, 0],
rotate: ['15deg', 0],
opacity: [0, 1],
easing: "easeOutCubic" },
offset).
add(
{
targets: nextImgs[1],
translateY: [600, 0],
rotate: ['-15deg', 0],
opacity: [0, 1],
easing: "easeOutCubic" },
"-=" + imgOffset).
add(
{
targets: nextImgs[2],
translateY: [600, 0],
rotate: ['15deg', 0],
opacity: [0, 1],
easing: "easeOutCubic" },
"-=" + imgOffset).
add(
{
targets: nextImgs[3],
translateY: [600, 0],
rotate: ['-15deg', 0],
opacity: [0, 1],
easing: "easeOutCubic" },
"-=" + imgOffset).
add(
{
targets: nextText,
translateY: ['.75em', 0],
/*clipPath: ['polygon(0 0, 100% 0, 100% 0, 0 0)','polygon(0 0, 100% 0, 100% 100%, 0% 100%)'],*/
opacity: [0, 1],
easing: "easeOutQuint",
duration: 600,
delay: (el, i) => 10 * (i + 1) },
offset);
}
let isPlaying = false;
function updateSlider(newIndex) {
const currentItem = items[current];
const newItem = items[newIndex];
function callback() {
currentItem.classList.remove("is-active");
newItem.classList.add("is-active");
current = newIndex;
isPlaying = false;
}
anim(currentItem, newItem, callback);
}
function next() {
if (isPlaying) return;
isPlaying = true;
const newIndex = current === items.length - 1 ? 0 : current + 1;
updateSlider(newIndex);
}
function prev() {
if (isPlaying) return;
isPlaying = true;
const newIndex = current === 0 ? items.length - 1 : current - 1;
updateSlider(newIndex);
}
nextBtn.onclick = next;
prevBtn.onclick = prev;
}
document.addEventListener("DOMContentLoaded", init);