11525 sujets

JavaScript, DOM et API Web HTML5

Hello.

J'ouvre un nouveau sujet, qui est en lien avec celui-ci https://forum.alsacreations.com/topic-5-90530-1-Resolu-Effet-de-survol-pour-changer-le-curseur.html

La solution proposée fonctionne très bien, mais j'avais pas anticipé la quantité d'élément, du coup en terme de perf c'est vraiment pas terrible.

Si vous avez des suggestions pour améliorer ça.


const mouseContainer = document.getElementById('mouse_container');
const mouseContent = document.querySelector('.mouse_content')

const navElement = document.querySelector('.navbar')
const chatElement = document.querySelector('.chat-window')
const categoryElement = document.querySelectorAll('.category-block')
const homeElement = document.querySelectorAll('.block-home')
const lastNewsElement = document.querySelector('.blockNewsActivity .lastNews h4');
const lastActivityElement = document.querySelector('.blockNewsActivity .lastActivity h4');
const lastActivityLinkElement = document.querySelectorAll('.blockNewsActivity .lastActivity .list-group a');
const toTopElement = document.getElementById('toTop')
const buttonElement = document.querySelectorAll('.btn')
const buttonTagElement = document.querySelectorAll('button')
const inputElement = document.querySelectorAll('input')
const textareaElement = document.querySelectorAll('textarea')
const selectElement = document.querySelectorAll('.select-selected')
const customSelectElement = document.querySelectorAll('customselect')
const linkElement = document.querySelectorAll('a')

const zoomOutElement = [
    navElement,
    chatElement,
    toTopElement
]

const buttonsElement = [
    buttonElement,
    buttonTagElement
]

const selectsElement = [
    selectElement,
    customSelectElement
]

const updateCursorPosition = (event) => {
    mouseContainer.style.top = `${event.clientY}px`;
    mouseContainer.style.left = `${event.clientX}px`;
}

function mouseHoverFunction(element = null, removeClass = null, addClass = null, content = null) {
    element.addEventListener('mouseenter', () => {
        mouseContainer.classList.remove(removeClass)
        mouseContainer.classList.add(addClass)
        mouseContent.innerHTML = content ? content : ''
    })
    element.addEventListener('mouseleave', () => {
        mouseContainer.classList.remove(addClass)
        mouseContent.innerHTML = ''
    })
}

window.addEventListener('mousemove', (event) => {
    updateCursorPosition(event)

    categoryElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'zoomOut', 'isHovering', el.querySelector('h3').innerText)
    })

    homeElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'zoomOut', 'isHovering', el.querySelector('h3').innerText)
    })

    if (lastNewsElement !== null) mouseHoverFunction(lastNewsElement, 'zoomOut', 'isHovering', lastNewsElement.innerText)

    if (lastActivityElement !== null) mouseHoverFunction(lastActivityElement, 'zoomOut', 'isHovering', lastActivityElement.innerText)

    zoomOutElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'isHovering', 'zoomOut')
    })

    lastActivityLinkElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'isHovering', 'zoomOut')
    })

    buttonsElement.forEach(btnEl => {
        btnEl.forEach(el => {
            if (el !== null) {
                if (el.querySelector('.fa-times')) mouseHoverFunction(el, 'zoomOut', 'svgHovering')
                else mouseHoverFunction(el, 'isHovering', 'zoomOut')
            }
        })
    })

    inputElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'isHovering', 'zoomOut')
    })

    textareaElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'isHovering', 'zoomOut')
    })

    selectsElement.forEach(sEle => {
        sEle.forEach(el => {
            if (el !== null) {
                if (el.querySelector('.fa-times')) mouseHoverFunction(el, 'zoomOut', 'svgHovering')
                else mouseHoverFunction(el, 'isHovering', 'zoomOut')
            }
        })
    })

    linkElement.forEach(el => {
        if (el !== null) mouseHoverFunction(el, 'isHovering', 'zoomOut')
    })
})



Merci Smiley cligne

PS: désolé pour le pavé
Modifié par _laurent (23 Jun 2023 - 14:51)
Modérateur
(re)-Salut !

Pourquoi ne pas utiliser une classe unique commune qui ne sert qu'a ça ? genre js-hover-effect que tu rajoute sur chaque élément que tu veux animer de la sorte.

Bonne journée Smiley smile
Re Smiley cligne

a écrit :
Pourquoi ne pas utiliser une classe unique commune qui ne sert qu'a ça ? genre js-hover-effect que tu rajoute sur chaque élément que tu veux animer de la sorte.


Hmm, le code, est assez merdique, y'en a dans tous les sens, j'ai repris le projet en cours de route.
Y'a plusieurs nomenclature de nommage ... Bref!

Je vais quand même voir ce que je peux faire, d'un côté ça me faciliterais grandement la tâche pour des petits truc, genre des icônes.
Merci et bonne journée !
Modifié par RhumIsis (23 Jun 2023 - 14:59)
Modérateur
RhumIsis a écrit :
le code, est assez merdique, y'en a dans tous les sens, j'ai repris le projet en cours de route.
Y'a plusieurs nomenclature de nommage ... Bref!

Mmmmh relou... Bon courage Smiley sweatdrop
Bonjour,

Alors certes, on ne maîtrise pas toujours le HTML sur lequel on travaille, mais on voit ici qu'une même fonction est répétée à de multiples endroits. On pourra toujours mettre les éléments récupérés dans un seul unique array, tous les autres tableaux étant fusionnés dans ce dernier, soit avec concat(), soit avec des spreads (...). Ce qui donnerait par exemple :
// On dit que el1, el2 et el3 sont des variables contenant des tableaux :
const els = [...el1, ...el2, ...el3]; // fusion avec des spreads

els.forEach(el => {
  if (el) mouseHoverFunction(el, 'isHovering', 'zoomOut')
})

PS : à quoi sert la condition el !== null ? Quitte à tester une condition de ce genre, je mettrais simplement :
if (el) {}

Ou même :
el && laFonction
Bonjour, bonjour.

J'étais parti sur une résolution de bug, puis une autre, puis une autre ...
Bref !

Avec cette façon de faire :
Olivier C a écrit :

// On dit que el1, el2 et el3 sont des variables contenant des tableaux :
const els = [...el1, ...el2, ...el3]; // fusion avec des spreads

els.forEach(el => {
  if (el) mouseHoverFunction(el, 'isHovering', 'zoomOut')
})


Je rencontre le même problème que l'autre poste. À savoir que dans le forEach je récupère uniquement le dernier élément de mon tableau el1, c'est pour ça que j'ai autant d'appel à la fonction mouseHoverFunction

Olivier C a écrit :

PS : à quoi sert la condition el !== null ? Quitte à tester une condition de ce genre, je mettrais simplement :
if (el) {}

Ou même :
el && laFonction

Parce que ... Smiley sleep Smiley lol

Du coup soit je m'y prend mal, soit je m'y prend mal.
Une idée ?
Modifié par RhumIsis (28 Jun 2023 - 16:58)
Je vois. Dans ce cas il faut ajouter un gestionnaire d'événement. Par exemple :
const els = [...el1, ...el2, ...el3]; // fusion avec des spreads

els.forEach(el => {
  el.addEventListener('mouseenter', () => { // le gestionnaire adéquat est à définir selon votre convenance
    if (el) mouseHoverFunction(el, 'isHovering', 'zoomOut')
  })
})

Je n'ai pas testé mais normalement ça doit être bon.
Meilleure solution
C'est tout bon.
J'ai supprimé la fonction
mouseHoverFunction()
pour éviter la redondance de l'event et j'ai créé une nouvelle fonction
searchForArray()
pour vérifier, à chaque itération des forEach, si l'élément est déjà dans mon tableau.

Pour ceux que ça pourrait intéresser, je laisse mon code ici.


const mouseContainer = document.getElementById('mouse-container');
const mouseContent = document.querySelector('.mouse-content')

const leaveElement = document.querySelectorAll('.mouse-leave-effect')
const enterElement = document.querySelectorAll('.mouse-enter-effect')

const updateCursorPosition = (event) => {
    mouseContainer.style.top = `${event.clientY}px`;
    mouseContainer.style.left = `${event.clientX}px`;
}

let els = [], leaveArray = [], enterArray = [];


function searchForArray(haystack, needle) {
    let i, j, current;
    for (i = 0; i < haystack.length; ++i) {
        if (needle.length === haystack[i].length) {
            current = haystack[i];
            for (j = 0; j < needle.length && needle[j] === current[j]; ++j) ;
            if (j === needle.length)
                return i;
        }
    }
    return -1;
}

window.addEventListener('mousemove', (event) => {
    updateCursorPosition(event)

    leaveElement.forEach(el => {
        if (searchForArray(enterArray, [el, 'isHovering', 'zoomOut']) === -1) {
            enterArray.push([el, 'isHovering', 'zoomOut'])
        }
    })

    enterElement.forEach(el => {
        let content
        if (el.children &&
            (el.children[0].classList.contains('title')
                || el.children[0].classList.contains('title-home')
                || el.children[0].classList.contains('category-name'))) {
            content = el.children[0].innerText
        } else {
            content = null
        }
        if (searchForArray(enterArray, [el, 'zoomOut', 'isHovering', content]) === -1) {
            enterArray.push([el, 'zoomOut', 'isHovering', content])
        }
    })

    els = [...leaveArray, ...enterArray]

    els.forEach(el => {
        let element = el[0], leaveClass = el[1], enterClass = el[2], content = el[3]

        element.addEventListener('mouseenter', () => {
            mouseContainer.classList.remove(leaveClass)
            mouseContainer.classList.add(enterClass)
            mouseContent.innerHTML = content ? content : ''
        })
        element.addEventListener('mouseleave', () => {
            mouseContainer.classList.remove(enterClass)
            mouseContent.innerHTML = ''
        })
    })
})



* {
                cursor: none !important;
            }
            body:hover #mouse-container {
                opacity: 1;
                width: 1.5em;
                height: 1.5em;
            }

            #mouse-container {
                display: flex;
                justify-content: center;
                align-items: center;
                width: 0;
                height: 0;
                border-radius: 50%;
                background-color: var(--primary-contrast-color);
                position: fixed;
                top: 0;
                opacity: 0;
                pointer-events: none;
                transform: translate(-50%, -50%);
                transition: transform .15s ease-in-out, width .15s ease-in-out, height .15s ease-in-out, opacity .15s ease-in-out, background-color .15s ease-in-out;
                z-index: 9999;
            }

            #mouse-container.isHovering {
                text-align: center;
                width: 6.5em !important;
                height: 6.5em !important;
                font-size: 20px;
                color: var(--default-color) !important;
            }

            #mouse-container.svgHovering {
                width: 3em !important;
                height: 3em !important;
                background-color: var(--primary-contrast-fade-color);
            }

            #mouse-container.zoomOut {
                width: .75em !important;
                height: .75em !important;
            }


Merci à vous deux Smiley cligne
Modifié par RhumIsis (30 Jun 2023 - 08:55)