Manage Carousel arrow rotation depending on the current slide
Right only when first and Left only when last
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
let carousel: EmblaCarouselType
|
||||
let currentSlide = 0
|
||||
let arrowDirection: string = null
|
||||
$: isFirstSlide = currentSlide === 0
|
||||
$: isLastSlide = currentSlide === slides.length - 1
|
||||
|
||||
|
||||
/** Navigate to specific slide */
|
||||
@@ -28,10 +30,19 @@
|
||||
*
|
||||
*/
|
||||
/** 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
|
||||
const { width } = carouselEl.getBoundingClientRect()
|
||||
if (isFirstSlide) {
|
||||
arrowDirection = 'next'
|
||||
} else if (isLastSlide) {
|
||||
arrowDirection = 'prev'
|
||||
} else {
|
||||
arrowDirection = offsetX < Math.round(width / 2) ? 'prev' : 'next'
|
||||
}
|
||||
|
||||
// Move arrow
|
||||
arrowPosition.set({
|
||||
@@ -70,15 +81,13 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="carousel {$$props.class ? $$props.class : ''}">
|
||||
{#if slides.length}
|
||||
<div class="carousel__viewport"
|
||||
bind:this={carouselEl}
|
||||
on:mousemove={throttle(handleArrowMove, 50)}
|
||||
<div class="carousel {$$props.class ? $$props.class : ''}"
|
||||
on:mousemove={handleArrowMove}
|
||||
on:click={handleArrowClick}
|
||||
>
|
||||
<div class="carousel__slides"
|
||||
>
|
||||
{#if slides.length}
|
||||
<div class="carousel__viewport" bind:this={carouselEl}>
|
||||
<div class="carousel__slides">
|
||||
{#each slides as { id, alt }}
|
||||
<Image
|
||||
class="carousel__slide"
|
||||
@@ -106,7 +115,7 @@
|
||||
|
||||
<span class="carousel__arrow" bind:this={arrowEl}
|
||||
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">
|
||||
<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" />
|
||||
|
||||
@@ -97,9 +97,16 @@
|
||||
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);
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
transition: transform 0.6s var(--ease-quart);
|
||||
}
|
||||
|
||||
// Flipped for previous direction
|
||||
&.is-flipped {
|
||||
transform: translate3d(var(--x), var(--y), 0) rotate(-180deg);
|
||||
svg {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user