I am attempting to make the fade in and out effect function properly in my slideshow

I've encountered an issue where the fading effect only occurs when the page initially loads and solely on the first image. Subsequently, the fading effect does not work on any other images displayed.

This is the CSS code I have implemented by adding it to

class="banner-items fade"
:

.fade {
  animation-name: fade;
  animation-duration: 1.5s;
}

@keyframes fade {
  from {opacity: .4}
  to {opacity: 1}
}

Additionally, I tried utilizing Svelte's transition:fade feature along with other techniques.

Here is the HTML component structure:

<div
    class="maestro-list"
    on:mouseenter={() => clearInterval(interval)} // pause and unpause
    on:mouseleave={() => {
        interval = setInterval(() => {
            current = (current + 1) % images.length
        }, delay)
    }}
>
    {#each images as image, index}
        <transition {index} {current} {delay}>
            <div class="banner-item">
                <span class="pic">
                    <img
                        src={image}
                        alt="dragon"
                        loading="lazy"
                        style="position:relative; display: {index === current ? 'block' : 'none'}"
                    />
                </span>
                <a class="banner_lnk" href="/">.</a>
            </div>
        </transition>
    {/each}
    <div class="num">
        {#each images as _, index}
            <span                      
                class="dot"
                tabindex="0"
                role="button"
                on:click={() => setcurrent(index)} //dot pagination
                class:active={index === current}
                on:keypress={(e) => {
                    if (e.key === "Enter") {
                        setcurrent(index)
                    }
                }}
            />
        {/each}
    </div>
</div>

TypeScript Script:

<script lang="ts">
    import { onMount, onDestroy } from "svelte"

    const images: string[] = ["/img-new-fixed.png", "/placeholder-9.png"]
    let current = 0
    let delay = 8000 // 8 seconds

    function setcurrent(index: number) {
        current = index
        clearInterval(interval)
        interval = setInterval(transition, delay)
    }

    function transition() {
        current = (current + 1) % images.length
    }

    let interval: NodeJS.Timeout

    onMount(() => {
        interval = setInterval(() => {
            current = (current + 1) % images.length
        }, delay)
    })

    onDestroy(() => {
        clearInterval(interval)
    })
</script>

One thing that comes to mind that I haven't explored yet is this example from Stack Overflow in the last answer given.

Furthermore, here's a reference where I drew inspiration for the Banner.

Answer №1

Check out this implementation using CSS Transitions and Svelte's class:directive

REPL

<script>
    import {urls} from './urls'
    import {onMount} from 'svelte'

    let index = 0
    let interval

    const start = () => interval = setInterval(() => index = (index + 1) % urls.length, 2500)
    const stop = () => clearInterval(interval)

    onMount(() => {
        start()
        return () => stop() //triggered when component is removed
    })

    function handleMarkerClick(i) {
        stop()
        index = i
    }
</script>

<div id="carousel">
    {#each urls as url, i}
    <img src={url} alt=""
             class:current-img={index === i}
             />
    {/each}
    <div id="carousel-nav">
        {#each urls as _, i}
        <svg height="20" width="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
            <circle cx="10" cy="10" r="10" 
                            class:current-marker="{index === i}"
                            on:click="{() => handleMarkerClick(i)}"
                            />
        </svg>
        {/each}
    </div>
</div>

<style>
    #carousel {
        position: relative;
        height: 500px;
    }
    img {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        opacity: 0;
        transition: opacity 500ms ease-out;
    }
    .current-img {
        opacity: 1;
    }
    #carousel-nav {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        bottom: 5%;
        display: grid;
        grid-auto-flow: column;
        gap: .5rem;
    }
    circle {
        fill: grey;
        transition: fill 500ms ease-out;
    }
    .current-marker {
        fill: white;
    }
</style>

Answer №2

Although I haven't worked with Svelte before, if I were to approach this using Vanilla HTML/CSS/JS, my focus would be on setting the animation-fill-mode to forwards for the animation. Additionally, I would manage the addition/removal of the .fade class based on button clicks while also resetting the opacity of elements accordingly.

In case it helps, here's how you could implement this in VanillaJS as an alternative way to visualize the concept:

const slides = Array.from(document.querySelectorAll(".slide"));
const buttonGroup = document.querySelector("#button-group");

buttonGroup.addEventListener("click", fadeSlides);

function fadeSlides(event) {
    const slideID = event.target.textContent;
    const slideSelector = `slide-${slideID}`;
    slides.forEach((el) => {
        if (el.id === slideSelector) {
            el.classList.add("fade");
        } else {
            el.classList.remove("fade");
            el.style.opacity = 0;
        }
    });
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Fade Example</title>
        <script defer src="app.js"></script>
        <style>
            #slideshow {
                width: 100px;
                height: 100px;
            }

            #button-group {
                margin-top: 12px;
            }

            .slide {
                width: 100px;
                height: 100px;
                position: absolute;
                top: 0;
                left: 0;
                opacity: 0;
            }

            #slide-1 {
                background-color: red;
                opacity: 1;
            }

            #slide-2 {
                background-color: green;
            }

            #slide-3 {
                background-color: blue;
            }
            .fade {
                animation-name: fade;
                animation-duration: 1.5s;
                animation-iteration-count: 1;
                animation-timing-function: ease-in;
                animation-fill-mode: forwards;
            }

            @keyframes fade {
                from {
                    opacity: 0;
                }
                to {
                    opacity: 1;
                }
            }
        </style>
    </head>
    <body>
        <div id="slideshow">
            <div class="slide" id="slide-1"></div>
            <div class="slide" id="slide-2"></div>
            <div class="slide" id="slide-3"></div>
        </div>
        <div id="button-group">
            <button id="button-1">1</button>
            <button id="button-2">2</button>
            <button id="button-3">3</button>
        </div>
    </body>
</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with TypeScript in Vue3: Unable to access computed property from another computed property

In my Vue3 project with TypeScript, I am encountering an issue where I am unable to access the properties of the returned JavaScript object from one computed property in another computed property using dot notation or named indexing. For instance, when tr ...

Flexible DIVs with a maximum width of 50% that adjust to different

I'm having trouble getting these two DIVs to display properly within a parent DIV while maintaining responsiveness. I want them to each take up 50% of the screen with a 10px margin between them. Does my current code approach seem correct? .box-cont ...

How can I show distinct values in the Angular Material dropdown menu?

I am currently working on implementing a feature where I need to show unique options for the select using angular material. Below is what I have so far: where appitem is an array of items. <mat-form-field> <mat-select placeholder="Select app ...

What is the process for obtaining the complete URL using the getDownloadURL() function along with a token?

An error occurred due to an unresolved FirebaseStorageError: "storage/object-not-found". The message indicates that the object 'k91a73uzb99' does not exist in Firebase Storage. This type of error is categorized under FirebaseError with a code of ...

How to retrieve values from multiple mat-sliders that are dynamically generated using ngFor loop

Creating multiple mat-sliders dynamically in Angular looks like this: <ng-container *ngFor="let parameter of parameterValues; let i = index;"> <mat-slider (input)="onInputChange($event)" min="1" max="{{ parameter.length }}" step="1" value="1" i ...

Combine both typescript and javascript files within a single Angular project

Is it feasible to include both TypeScript and JavaScript files within the same Angular project? I am working on a significant Angular project and considering migrating it to TypeScript without having to rename all files to .ts and address any resulting er ...

How can RootStateOrAny be turned off in React with typescript?

Whenever I need to employ useSelector, I find myself repeating this pattern: const isLoading = useSelector( (state) => state.utils.isLoading ); Is there a shortcut to avoid typing out RootStateOrAny each time? It's starting to become a hassl ...

Maximizing the width of navbar elements with Bootstrap 3

I am currently working on building a webpage with bootstrap3, but I have encountered an issue with the navigation bar. I would like the navigation links ("Web Design", "Development", "Photography", "Blog") to be evenly spaced out within the horizontal na ...

Cypress: Conducting Test with Custom Timezone Setting on Windows

My testing environment was set up to run in UTC time zone. I utilized cy.clock() to initialize a date-time in UTC format, which the Web App will then display as the current browser date-time in UTC. In order to achieve this, I ensured TZ=UTC in my environ ...

A guide on showcasing nested arrays data in an Angular application

info = [ { list: [ { title: 'apple'} ] }, { list: [ { title: 'banana'} ] } ] My goal here is to extract the list items. Here is how they are structured. desired r ...

What is the best way to implement padding for two DIVS on a screen utilizing VH and VW units to ensure they fill up the

I am currently working on a layout with two columns spanning across the page. I need to add some padding around the text in each column so that it sits nicely in the middle. I have been trying to adjust the div width and use wrappers, but something seems t ...

Struggling to align list-items in a horizontal manner

I'm having trouble aligning the list-items in my horizontal navbar. Can anyone assist me in identifying the error? Below is the HTML code, which has a complex structure due to the use of the Wordpress thesis theme and Cufon for font replacement: < ...

Is it possible to manually activate a dropdown event using pure JavaScript?

I am attempting to manually trigger a dropdown event using JavaScript. Below is the function where I am trying to achieve this. I have successfully halted the initial event that occurs and now I need to initiate a dropdown event. stopNavigationTriggerDrop ...

Determining the type relationship between two generic types when using a union

Here is the code snippet defining a React component using react-hook-form: import { type FieldPath, type FieldValues, type FieldPathValue, } from "react-hook-form"; interface FormControlRadioBoxProps< TFieldValues extends FieldValue ...

Tips for achieving asynchronous data retrieval using Angular Observable inside another Observable

What is my goal? I have several components with similar checks and data manipulation activities. I aim to centralize these operations in an observable. To do this, I created an observable called "getData" within my service... The unique aspect of "getData ...

Automatically select a value in MUI AutoComplete and retrieve the corresponding object

I recently set up a list using the MUI (v4) Select component. I've received a feature request to make this list searchable due to its extensive length. Unfortunately, it appears that the only option within MUI library for this functionality is the Au ...

Unable to access property value following AJAX call

Here is my code snippet: constructor(props: any) { super(props); this.state = { list: [], }; } public componentWillMount() { this.loadData(); } public loadData = () => { axios.get(someURL) .then((response) = ...

Is it possible to customize the color of an SVG image within Next.js using next/image?

import Image from 'next/image' ... <Image src="/emotion.svg" alt="emtion" width={50} height={50} /> I am trying to change the color of the SVG using next/image. However, applying the following CSS rule does not seem ...

Struggling to center an image within a CSS border

I'm attempting to include a subtle border around an icon. The issue I am facing is that the image is positioned at the top of the bordered area, whereas I want it centered. Here's how it currently appears: This is my current border CSS style: ...

Assign a CSS class to a specific option within a SelectField in a WTForms form

Could someone explain the process of assigning a CSS class to the choices values? I am looking to customize the background of each choice with a small image. How can this be done using wtforms and CSS? class RegisterForm(Form): username = TextField( ...