dashersupply/src/components/ImageCarousel.astro

252 lines
6.2 KiB
Plaintext

---
import type { Brand } from '../data/brands/brand';
export interface Image {
src: string;
alt?: string;
title?: string;
}
interface Props {
images: Image[];
dots?: number;
}
const { images } = Astro.props;
let index = 1;
---
<!-- Slideshow container -->
<image-carousel>
<!-- Full-width images with number and caption text -->
{images?.map(image => (
<div class="carousel-slide carousel-fade">
<div class="carousel-number">
{index++} of {images.length}
</div>
<img class="carousel-img" src={image.src} />
{image.title &&
<div class="carousel-caption" class="text">
{image.title}
</div>
}
</div>
))}
<!-- Next and previous buttons -->
<div class="carousel-btn-prev">
<div class="overlay"></div>
<a>
<span>&#10094;</span>
<div class="dummy"></div>
</a>
</div>
<div class="carousel-btn-next">
<div class="overlay"></div>
<a>
<span>&#10095;</span>
<div class="dummy"></div>
</a>
</div>
</image-carousel>
<script>
class ImageCarousel extends HTMLElement {
slideIndex: number;
constructor() {
super();
this.slideIndex = 1;
const prevButton = $(this).find('.carousel-btn-prev');
const nextButton = $(this).find('.carousel-btn-next');
prevButton.click((evt: Event) => {
this.plusSlides(-1);
});
nextButton.click((evt: Event) => {
this.plusSlides(1);
});
this.showSlide(this.slideIndex);
}
slidesCount() {
return $(this).find('.carousel-slide').length || 0;
}
plusSlides(plusIncrement: number) {
this.showSlide(this.slideIndex + plusIncrement);
}
showSlide(slideIndex: number) {
const firstSlide = 1;
const slidesCount = this.slidesCount();
if (slideIndex < firstSlide) slideIndex = slidesCount;
if (slideIndex > slidesCount) slideIndex = 1;
this.slideIndex = slideIndex;
let slides = $(this).find('.carousel-slide');
slides.each((index) => $(slides[index]).toggleClass('carousel-slide-current', false));
$(slides[slideIndex-1]).toggleClass('carousel-slide-current', true);
console.log("Showing slide " + slideIndex + " of " + slidesCount + ".");
// var dots = $(carousel).find('.carousel-dot');
// for (var i = 0; i < dots.length; i++) {
// dots[i].className = dots[i].className.replace(" active", "");
// }
// dots[slideIndex-1].className += " active";
}
}
customElements.define('image-carousel', ImageCarousel);
</script>
<style>
image-carousel {
position: relative;
display: grid;
box-sizing: border-box;
border-radius: 7px;
}
.carousel-slide {
display: none;
}
.carousel-slide-current {
display: block !important;
}
.carousel-slide img {
width: 100%;
border-radius: 7px;
}
.carousel-btn-prev, .carousel-btn-next {
cursor: pointer;
position: absolute;
top: 0;
width: 6rem;
height: 100%;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
text-decoration: none;
user-select: none;
vertical-align: middle;
white-space: nowrap;
font-size: 0;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
}
.carousel-btn-prev, .carousel-btn-prev .overlay {
border-radius: 7px 0 0 7px;
}
.carousel-btn-next, .carousel-btn-next .overlay {
right: 0;
border-radius: 0 7px 7px 0;
}
.carousel-btn-prev > a, .carousel-btn-next > a {
position: relative;
display: block;
text-align: center;
/* height: 100%; */
width: 100%;
background-color: transparent;
opacity: 1;
color: #63666d;
filter: invert(1);
mix-blend-mode: difference;
display: flex;
align-items: center;
justify-content: center;
}
/* .carousel-btn-prev > a span, .carousel-btn-next > a span {
position: relative;
top: 50%;
bottom: 50%;
width: 40px;
left: 0px;
} */
.carousel-btn-prev .dummy, .carousel-btn-next .dummy {
height: 100%;
}
.carousel-btn-prev .overlay, .carousel-btn-next .overlay {
position: absolute;
top: 0;
width: 100%;
left: 0;
height: 100%;
background-color: transparent;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.carousel-btn-prev span, .carousel-btn-next span {
font-size: 1.2rem;
position: relative;
top: 50%;
}
.carousel-btn-prev:is(:hover, :focus-within) > .overlay, .carousel-btn-next:is(:hover, ::focus-within) > .overlay {
background-color: #23262d;
opacity: 0.8;
}
.carousel-btn-prev:is(:hover, :focus-within) > a, .carousel-btn-next:is(:hover, ::focus-within) > a {
opacity: 0.8;
color: #fff;
/* background-color: #23262d; */
filter: unset;
mix-blend-mode: unset;
}
.carousel-btn-prev:is(:hover, :focus-within), .carousel-btn-next:is(:hover, :focus-within) {
background-color: #23262d;
background-image: none;
background-size: 400%;
background-position: 100%;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
background-position: 0;
background-image: var(--accent-gradient);
background-size: 400%;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.carousel-caption {
color: #000;
font-size: 15px;
padding: 8px 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
filter: invert(1);
mix-blend-mode: difference;
}
.carousel-number {
color: #23262d;
text-shadow: 1px 1px 2px #fff, 0 0 1em #ccc, 0 0 0.2em #23262d;
font-size: 0.8em;
font-weight: 800;
padding: 8px 12px;
position: absolute;
left: 40%;
right: 40%;
width: 20%;
text-align: center;
top: 0;
filter: invert(1);
mix-blend-mode: luminosity;
}
.carousel-dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active, .dot:hover {
background-color: #717171;
}
.carousel-fade {
animation-name: fade;
animation-duration: 0.6s;
}
@keyframes fade {
from {opacity: .1}
to {opacity: 1}
}
</style>