Carousel: Use the counter as a component
- Add animation when changing photos - Reusable and scalable to more than XX photos
This commit is contained in:
37
src/atoms/Counter.svelte
Normal file
37
src/atoms/Counter.svelte
Normal file
@@ -0,0 +1,37 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
// Props
|
||||
export let currentIndex = 0
|
||||
export let className = null
|
||||
|
||||
// Variables
|
||||
$: actualIndex = currentIndex + 1
|
||||
$: amount = String(actualIndex).length
|
||||
$: index = (actualIndex < 10) ? String(actualIndex).padStart(2, '0') : String(actualIndex)
|
||||
$: digits = index.split('')
|
||||
let counter
|
||||
const numbers = [...Array(10).keys()]
|
||||
|
||||
|
||||
/*
|
||||
** Run code when mounted
|
||||
*/
|
||||
onMount(() => {
|
||||
// Set each digit column's height = its spans combined (in order to translate in tens of %)
|
||||
counter.querySelectorAll('div').forEach(column => {
|
||||
const spans = column.querySelectorAll('span')
|
||||
column.style.height = spans[0].offsetHeight * spans.length + 'px'
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="counter {className}" bind:this={counter}>
|
||||
{#each digits as digit}
|
||||
<div class="counter__column" style="transform: translateY(-{digit}0%);">
|
||||
{#each numbers as number}
|
||||
<span>{number}</span>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
// Components
|
||||
import IconArrow from '../atoms/IconArrow'
|
||||
import Counter from '../atoms/Counter'
|
||||
|
||||
// Props
|
||||
export let photos
|
||||
@@ -42,6 +43,9 @@
|
||||
} else if (direction === 'next') {
|
||||
currentIndex++
|
||||
currentIndex = (currentIndex >= photos.length) ? 0 : currentIndex
|
||||
} else {
|
||||
currentIndex = direction
|
||||
console.log('Go to photo', direction, currentIndex)
|
||||
}
|
||||
|
||||
// Send current photo to event
|
||||
@@ -182,9 +186,7 @@
|
||||
</div>
|
||||
|
||||
{#if viewer}
|
||||
<div class="carousel__number">
|
||||
{currentIndex < 10 ? 0 : ''}{photos.length - currentIndex}
|
||||
</div>
|
||||
<Counter {currentIndex} className="carousel__number" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -207,25 +209,13 @@
|
||||
<p class="carousel__date">{formatDate(currentPhoto.date, 'FULL')}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if !viewer}
|
||||
<ol class="carousel__dots">
|
||||
{#each photos as page, index}
|
||||
<li class:active={page === currentPhoto} on:click={() => currentIndex = index}>
|
||||
<button aria-label="Go to photo #{index + 1}"></button>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if viewer}
|
||||
<ol class="carousel__dots">
|
||||
{#each photos as page}
|
||||
<li class:active={page === currentPhoto}>
|
||||
<button></button>
|
||||
{#each photos as page, index}
|
||||
<li class:active={page === currentPhoto} on:click={() => goToPhoto(index)}>
|
||||
<button aria-label="Go to photo #{index + 1}"></button>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
22
src/style/atoms/_counter.scss
Normal file
22
src/style/atoms/_counter.scss
Normal file
@@ -0,0 +1,22 @@
|
||||
// Counter
|
||||
.counter {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
font-family: $font-serif-extra;
|
||||
font-size: pxVW(672);
|
||||
color: rgba($color-tertiary, 0.4);
|
||||
text-align: center;
|
||||
// pointer-events: none;
|
||||
// user-select: none;
|
||||
|
||||
// Column
|
||||
&__column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 0.85;
|
||||
text-align: right;
|
||||
margin: 0 -16px;
|
||||
transition: transform 0.6s $ease-quart;
|
||||
will-change: transform;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,10 @@
|
||||
max-width: 1280px;
|
||||
padding: 0;
|
||||
|
||||
@include breakpoint (1600px) {
|
||||
@include breakpoint (sm) {
|
||||
max-width: 85%;
|
||||
}
|
||||
@include breakpoint (1680px) {
|
||||
max-width: 1424px;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +23,6 @@
|
||||
z-index: 2;
|
||||
margin: 0 auto;
|
||||
|
||||
@include breakpoint (sm) {
|
||||
max-width: 85%;
|
||||
}
|
||||
@include breakpoint (xl) {
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -194,7 +194,11 @@
|
||||
&__locations {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 128px;
|
||||
min-height: 56px;
|
||||
|
||||
@include breakpoint (sm) {
|
||||
min-height: 128px;
|
||||
}
|
||||
}
|
||||
|
||||
// Location
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
@import "atoms/toggle";
|
||||
@import "atoms/link";
|
||||
@import "atoms/switcher";
|
||||
@import "atoms/counter";
|
||||
|
||||
// Molecules
|
||||
@import "molecules/location";
|
||||
|
||||
Reference in New Issue
Block a user