Manage Carousel arrow rotation depending on the current slide

Right only when first and Left only when last
This commit is contained in:
2021-11-03 18:45:18 +01:00
parent 365b8f5390
commit 18f2e324c7
2 changed files with 29 additions and 13 deletions

View File

@@ -13,6 +13,8 @@
let carousel: EmblaCarouselType let carousel: EmblaCarouselType
let currentSlide = 0 let currentSlide = 0
let arrowDirection: string = null let arrowDirection: string = null
$: isFirstSlide = currentSlide === 0
$: isLastSlide = currentSlide === slides.length - 1
/** Navigate to specific slide */ /** Navigate to specific slide */
@@ -28,10 +30,19 @@
* *
*/ */
/** Move arrow and define direction on mousemove */ /** Move arrow and define direction on mousemove */
const handleArrowMove = ({ offsetX, offsetY }: MouseEvent) => { const handleArrowMove = (event: MouseEvent) => {
const { left, top, width } = carouselEl.getBoundingClientRect()
const offsetX = event.clientX - left
const offsetY = event.clientY - top
// Define direction // Define direction
const { width } = carouselEl.getBoundingClientRect() if (isFirstSlide) {
arrowDirection = offsetX < Math.round(width / 2) ? 'prev' : 'next' arrowDirection = 'next'
} else if (isLastSlide) {
arrowDirection = 'prev'
} else {
arrowDirection = offsetX < Math.round(width / 2) ? 'prev' : 'next'
}
// Move arrow // Move arrow
arrowPosition.set({ arrowPosition.set({
@@ -70,15 +81,13 @@
}) })
</script> </script>
<div class="carousel {$$props.class ? $$props.class : ''}"> <div class="carousel {$$props.class ? $$props.class : ''}"
on:mousemove={handleArrowMove}
on:click={handleArrowClick}
>
{#if slides.length} {#if slides.length}
<div class="carousel__viewport" <div class="carousel__viewport" bind:this={carouselEl}>
bind:this={carouselEl} <div class="carousel__slides">
on:mousemove={throttle(handleArrowMove, 50)}
on:click={handleArrowClick}
>
<div class="carousel__slides"
>
{#each slides as { id, alt }} {#each slides as { id, alt }}
<Image <Image
class="carousel__slide" class="carousel__slide"
@@ -106,7 +115,7 @@
<span class="carousel__arrow" bind:this={arrowEl} <span class="carousel__arrow" bind:this={arrowEl}
style="--x: {$arrowPosition.x}px; --y: {$arrowPosition.y}px;" style="--x: {$arrowPosition.x}px; --y: {$arrowPosition.y}px;"
class:is-flipped={arrowDirection === 'prev'} class:is-flipped={arrowDirection === 'prev' && !isFirstSlide || isLastSlide}
> >
<svg width="29" height="32" viewBox="0 0 29 32" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <svg width="29" height="32" viewBox="0 0 29 32" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.82 28.275a2.182 2.182 0 0 0 3.086 3.086l13.818-13.818a2.182 2.182 0 0 0 0-3.086L13.906.64a2.182 2.182 0 1 0-3.085 3.086l10.093 10.093H2.182a2.182 2.182 0 1 0 0 4.364h18.732L10.821 28.275Z" /> <path fill-rule="evenodd" clip-rule="evenodd" d="M10.82 28.275a2.182 2.182 0 0 0 3.086 3.086l13.818-13.818a2.182 2.182 0 0 0 0-3.086L13.906.64a2.182 2.182 0 1 0-3.085 3.086l10.093 10.093H2.182a2.182 2.182 0 1 0 0 4.364h18.732L10.821 28.275Z" />

View File

@@ -97,9 +97,16 @@
transform-origin: 50% 50%; transform-origin: 50% 50%;
filter: drop-shadow(0 2px 2px $color-shadow) drop-shadow(0 8px 8px $color-shadow) drop-shadow(0 16px 16px $color-shadow); filter: drop-shadow(0 2px 2px $color-shadow) drop-shadow(0 8px 8px $color-shadow) drop-shadow(0 16px 16px $color-shadow);
svg {
display: block;
transition: transform 0.6s var(--ease-quart);
}
// Flipped for previous direction // Flipped for previous direction
&.is-flipped { &.is-flipped {
transform: translate3d(var(--x), var(--y), 0) rotate(-180deg); svg {
transform: rotate(-180deg);
}
} }
} }