Skip to content

Commit

Permalink
Added secondary carousel component
Browse files Browse the repository at this point in the history
  • Loading branch information
Fer-Bar committed Feb 15, 2024
1 parent 9f26f93 commit ed8eaf6
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 0 deletions.
102 changes: 102 additions & 0 deletions pet/static/pet/css/secondary_carousel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
.wrapper-carousel {
width: 100%;
position: relative;
}
.wrapper-carousel i {
top: 50%;
height: 50px;
width: 50px;
cursor: pointer;
font-size: 1.25rem;
position: absolute;
text-align: center;
line-height: 50px;
background: #fff;
border-radius: 50%;
box-shadow: 0 3px 6px rgba(0,0,0,0.23);
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper-carousel i:active{
transform: translateY(-50%) scale(0.85);
}
.wrapper-carousel i:first-child{
left: -22px;
}
.wrapper-carousel i:last-child{
right: -22px;
}
.wrapper-carousel .carousel-secondary{
display: grid;
grid-auto-flow: column;
grid-auto-columns: calc((100% / 3));
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 16px;
border-radius: 8px;
scroll-behavior: smooth;
scrollbar-width: none;
}
.carousel-secondary::-webkit-scrollbar {
display: none;
}
.carousel-secondary.no-transition {
scroll-behavior: auto;
}
.carousel-secondary.dragging {
scroll-snap-type: none;
scroll-behavior: auto;
}
.carousel-secondary.dragging .card-secondary {
cursor: grab;
user-select: none;
}
.carousel-secondary :where(.card-secondary, .card-img) {
display: flex;
justify-content: center;
align-items: center;
}
.carousel-secondary .card-secondary {
scroll-snap-align: start;
height: 342px;
list-style: none;
background: #fff;
cursor: pointer;
padding-bottom: 15px;
flex-direction: column;
border-radius: 8px;
}
.carousel-secondary .card-secondary .card-img {
background: #bc5148;
height: 148px;
width: 148px;
border-radius: 50%;
}
.card-secondary .card-img img {
width: 140px;
height: 140px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #fff;
}
.carousel-secondary .card-secondary h2 {
font-weight: 500;
font-size: 1.56rem;
margin: 30px 0 5px;
}
.carousel-secondary .card-secondary span {
color: #6A6D78;
font-size: 1.31rem;
}

@media screen and (max-width: 990px) {
.wrapper-carousel .carousel-secondary {
grid-auto-columns: calc((100% / 2));
}
}

@media screen and (max-width: 600px) {
.wrapper-carousel .carousel-secondary {
grid-auto-columns: 110%;
}
}
84 changes: 84 additions & 0 deletions pet/static/pet/js/carousel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const wrapper = document.querySelector(".wrapper-carousel");
const carousel = document.querySelector(".carousel-secondary");
const firstCardWidth = carousel.querySelector(".card-secondary").offsetWidth;
const arrowBtns = document.querySelectorAll(".wrapper-carousel i");
const carouselChildren = [...carousel.children];

let isDragging = false, isAutoPlay = false, startX, startScrollLeft, timeoutId;

// Get the number of cards that can fit in the carousel at once
let cardPerView = Math.round(carousel.offsetWidth / firstCardWidth);

// Insert copies of the last few cards to beginning of carousel for infinite scrolling
carouselChildren.slice(-cardPerView).reverse().forEach(card => {
carousel.insertAdjacentHTML("afterbegin", card.outerHTML);
});

// Insert copies of the first few cards to end of carousel for infinite scrolling
carouselChildren.slice(0, cardPerView).forEach(card => {
carousel.insertAdjacentHTML("beforeend", card.outerHTML);
});

// Scroll the carousel at appropriate position to hide first few duplicate cards on Firefox
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");

// Add event listeners for the arrow buttons to scroll the carousel left and right
arrowBtns.forEach(btn => {
btn.addEventListener("click", () => {
carousel.scrollLeft += btn.id === "left" ? -firstCardWidth : firstCardWidth;
});
});

const dragStart = (e) => {
isDragging = true;
carousel.classList.add("dragging");
// Records the initial cursor and scroll position of the carousel
startX = e.pageX;
startScrollLeft = carousel.scrollLeft;
}

const dragging = (e) => {
if(!isDragging) return; // if isDragging is false return from here
// Updates the scroll position of the carousel based on the cursor movement
carousel.scrollLeft = startScrollLeft - (e.pageX - startX);
}

const dragStop = () => {
isDragging = false;
carousel.classList.remove("dragging");
}

const infiniteScroll = () => {
// If the carousel is at the beginning, scroll to the end
if(carousel.scrollLeft === 0) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.scrollWidth - (2 * carousel.offsetWidth);
carousel.classList.remove("no-transition");
}
// If the carousel is at the end, scroll to the beginning
else if(Math.ceil(carousel.scrollLeft) === carousel.scrollWidth - carousel.offsetWidth) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
}

// Clear existing timeout & start autoplay if mouse is not hovering over carousel
clearTimeout(timeoutId);
if(!wrapper.matches(":hover")) autoPlay();
}

const autoPlay = () => {
if(window.innerWidth < 800 || !isAutoPlay) return; // Return if window is smaller than 800 or isAutoPlay is false
// Autoplay the carousel after every 2500 ms
timeoutId = setTimeout(() => carousel.scrollLeft += firstCardWidth, 2500);
}
autoPlay();

carousel.addEventListener("mousedown", dragStart);
carousel.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", dragStop);
carousel.addEventListener("scroll", infiniteScroll);
wrapper.addEventListener("mouseenter", () => clearTimeout(timeoutId));
wrapper.addEventListener("mouseleave", autoPlay);
38 changes: 38 additions & 0 deletions pet/templates/pet/secondary_carousel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<div class="container">
<div class="wrapper-carousel">
<i id="left" class="fa-solid fa-angle-left"></i>
<ul class="carousel-secondary">
<li class="card-secondary">
<div class="card-img"><img src="https://fer-bar.github.io/AlberCan/images/article2.jpg" alt="img" draggable="false"></div>
<h2>Blanche Pearson</h2>
<span>Sales Manager</span>
</li>
<li class="card-secondary">
<div class="card-img"><img src="https://fer-bar.github.io/AlberCan/images/article3.jpg" alt="img" draggable="false"></div>
<h2>Joenas Brauers</h2>
<span>Web Developer</span>
</li>
<li class="card-secondary">
<div class="card-img"><img src="https://fer-bar.github.io/AlberCan/images/pet1.jpg" alt="img" draggable="false"></div>
<h2>Lariach French</h2>
<span>Online Teacher</span>
</li>
<li class="card-secondary">
<div class="card-img"><img src="https://fer-bar.github.io/AlberCan/images/pet2.jpg" alt="img" draggable="false"></div>
<h2>Iver Don Fallas</h2>
<span>Alcoholico</span>
</li>
<li class="card-secondary">
<div class="card-img"><img src="https://fer-bar.github.io/AlberCan/images/pet3.jpg" alt="img" draggable="false"></div>
<h2>Kristina Zasiadko</h2>
<span>Bank Manager</span>
</li>
<li class="card-secondary">
<div class="card-img"><img src="https://fer-bar.github.io/AlberCan/images/pet4.jpg" alt="img" draggable="false"></div>
<h2>Donald Horton</h2>
<span>App Designer</span>
</li>
</ul>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</div>

0 comments on commit ed8eaf6

Please sign in to comment.