233 lines
6.3 KiB
Svelte
233 lines
6.3 KiB
Svelte
<script>
|
|
import { swipe } from "svelte-gestures";
|
|
import SvgIcon from "@jamescoyle/svelte-icon";
|
|
import { mdiArrowRight, mdiArrowLeft, mdiRestore } from "@mdi/js";
|
|
import "$lib/css/slideshow.css";
|
|
import { onMount } from "svelte";
|
|
import {
|
|
createTimeLine,
|
|
updateTimeLine,
|
|
slideContainerCount,
|
|
slideTimelineCount,
|
|
slideStringCount,
|
|
} from "$lib/js/slideshow.js";
|
|
|
|
// Exported values
|
|
export let data = [];
|
|
export let type;
|
|
export let timeline = false;
|
|
export let reverse = false;
|
|
export let show_max_index = false;
|
|
if (reverse) {
|
|
data = data.reverse();
|
|
}
|
|
|
|
// Svelte bindings
|
|
let windowWidth = 0;
|
|
|
|
// Resizing variables
|
|
let resizing = false;
|
|
|
|
// Slideshow global variables
|
|
let slideshow_index = 0;
|
|
let slideshow_hidden = [];
|
|
let slideshowTimeline;
|
|
let slideshowElements;
|
|
let slideshowBubbles;
|
|
|
|
// Timeline global variables
|
|
let slideshow;
|
|
let bubbles = [];
|
|
|
|
onMount(() => {
|
|
/* Slideshow */
|
|
//global writer count
|
|
const currentSlideCount = $slideContainerCount;
|
|
// Sliced array from currentSlideCount to data.length
|
|
slideshowElements = Array.from(
|
|
document.querySelectorAll(".slide-container"),
|
|
).slice(currentSlideCount, currentSlideCount + data.length);
|
|
// Updating with the current length
|
|
slideContainerCount.update((value) => {
|
|
return value + data.length;
|
|
});
|
|
|
|
if (timeline) {
|
|
/* SlideTimeline */
|
|
//global writer count
|
|
const currentTimelineCount = $slideTimelineCount;
|
|
// Creating the string between the bubbles
|
|
slideshowBubbles = Array.from(
|
|
document.querySelectorAll(".slide-bubble"),
|
|
).slice(currentTimelineCount, currentTimelineCount + data.length);
|
|
|
|
// Creating strings
|
|
for (const element of slideshowBubbles) {
|
|
bubbles.push({
|
|
left: element.offsetLeft,
|
|
top: element.offsetTop,
|
|
});
|
|
}
|
|
|
|
createTimelineStrings();
|
|
}
|
|
});
|
|
|
|
function slideCards(advance) {
|
|
// Set or reset slideshow index, hidden array and timeling.
|
|
if (advance) {
|
|
if (slideshow_index >= data.length - 1) {
|
|
resetSlideCards();
|
|
} else {
|
|
slideshow_hidden.push(slideshow_index);
|
|
slideshow_index++;
|
|
}
|
|
} else {
|
|
slideshow_hidden.pop();
|
|
slideshow_index--;
|
|
}
|
|
|
|
// Incrementing the transformValue for each element
|
|
let transformValue = 0;
|
|
for (const id of slideshow_hidden) {
|
|
transformValue += slideshowElements[id].clientWidth;
|
|
}
|
|
|
|
// Translating elements
|
|
slideshowElements.forEach((element, id) => {
|
|
/* Slideshow translating*/
|
|
let newtransformValue = transformValue;
|
|
if (slideshow_hidden.includes(id)) {
|
|
// 1.1 because when in 'unactive' state, the scale is 0.9, adjusting the actual ratio
|
|
newtransformValue *= 1.1;
|
|
}
|
|
element.style.transform = `translateX(-${newtransformValue}px)`;
|
|
|
|
/* Slideshow Timeline translating */
|
|
if (timeline) {
|
|
if (slideshowTimeline[id] != undefined) {
|
|
slideshowTimeline[id].style.transform =
|
|
`translateX(-${transformValue}px)`;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function resetSlideCards() {
|
|
return new Promise((resolve) => {
|
|
slideshow_hidden = [];
|
|
slideshow_index = 0;
|
|
for (const element of slideshowElements) {
|
|
element.style.transform = "";
|
|
}
|
|
if (timeline) {
|
|
for (const timeline of slideshowTimeline) {
|
|
timeline.style.transform = "";
|
|
}
|
|
}
|
|
|
|
resolve();
|
|
});
|
|
}
|
|
|
|
function createTimelineStrings() {
|
|
const stringTimelineElements = createTimeLine(bubbles);
|
|
for (const div of stringTimelineElements) {
|
|
slideshow.appendChild(div);
|
|
}
|
|
// Updating with the current length
|
|
slideTimelineCount.update((value) => {
|
|
return value + data.length;
|
|
});
|
|
|
|
//global writer count
|
|
const currentStringCount = $slideStringCount;
|
|
/* Sliced array from currentTimelineCount to data.length
|
|
Everytime a slideshow created the slide string, the queryselector all will get all the elements
|
|
We do not want that and only want the slide-string we are interested in
|
|
Starting from the oldest count, finishing by our actual length */
|
|
slideshowTimeline = Array.from(
|
|
document.querySelectorAll(".slide-string"),
|
|
).slice(
|
|
currentStringCount,
|
|
currentStringCount + stringTimelineElements.length,
|
|
);
|
|
// Updating with the current length
|
|
slideStringCount.update((value) => {
|
|
return value + stringTimelineElements.length;
|
|
});
|
|
}
|
|
|
|
// Mobile swipe
|
|
function mobileSwipe(event) {
|
|
if (slideshow_index > 0 || event.detail.direction == "left")
|
|
slideCards(event.detail.direction == "left");
|
|
}
|
|
|
|
async function changeSize() {
|
|
if (timeline && !resizing) {
|
|
resizing = true;
|
|
|
|
await resetSlideCards();
|
|
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
updateTimeLine(slideshowTimeline, slideshowBubbles);
|
|
resizing = false;
|
|
//global writer count
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:window on:resize={changeSize} bind:innerWidth={windowWidth} />
|
|
|
|
<div
|
|
class="slideshow"
|
|
use:swipe={{ timeframe: 300, minSwipeDistance: 100, touchAction: "pan-y" }}
|
|
on:swipe={mobileSwipe}
|
|
bind:this={slideshow}
|
|
>
|
|
<button
|
|
class={slideshow_index >= 1
|
|
? "slideshow_btn"
|
|
: "slideshow_btn slideshow_btn_center"}
|
|
on:click={() => slideCards(true)}
|
|
>
|
|
<div>
|
|
<SvgIcon
|
|
size={windowWidth < 1000 ? "30" : "45"}
|
|
path={slideshow_index >= data.length - 1 ? mdiRestore : mdiArrowRight}
|
|
type="mdi"
|
|
/>
|
|
</div>
|
|
</button>
|
|
<button
|
|
class={slideshow_index >= 1
|
|
? "slideshow_btn slideshow_btn_low"
|
|
: "slideshow_btn slideshow_btn_low slideshow_btn_disabled"}
|
|
on:click={() => {
|
|
if (slideshow_index >= 1) slideCards(false);
|
|
}}
|
|
>
|
|
<SvgIcon
|
|
size={windowWidth < 1000 ? "30" : "45"}
|
|
path={mdiArrowLeft}
|
|
type="mdi"
|
|
/>
|
|
</button>
|
|
{#each data as selected_data, index (index)}
|
|
{#if show_max_index}
|
|
<svelte:component
|
|
this={type}
|
|
data={selected_data}
|
|
active={index == slideshow_index ? true : false}
|
|
max={data.length}
|
|
actualnum={index + 1}
|
|
/>
|
|
{:else}
|
|
<svelte:component
|
|
this={type}
|
|
data={selected_data}
|
|
active={index == slideshow_index ? true : false}
|
|
/>
|
|
{/if}
|
|
{/each}
|
|
</div>
|