Gloubi tuto – un menu interactif Hello Kitty

Bienvenue sur ce premier gloubi tuto (pour en savoir plus sur les gloubi tutos) qui concerne un menu interactif avec Hello Kitty.

Présentation et explication de l’existant

Pour voir la source du script actuel, RDV sur cette page du site de notre nouvel adversaire dans la guerre du gloubi.

Le HTML

Les éléments sont au nombre de 8 (tous dans leurs propres div, elles-même contenues dans une div englobante) :

– une image de la tête de Kitty

– ses jambes

– et six images correspondant aux entrées de notre menu

Le CSS

Ces 8 éléments sont tous positionnés de manière absolue, et disposés sur 3 « calques » (définis en utilisant le z-index) pour permettre aux liens de passer au-dessus des jambes, mais en-dessous de la tête.

Le JavaScript

Le JavaScript est là pour déplacer tous les liens le long d’une trajectoire elliptique, d’un certain intervalle (ici π / 180) toutes les x millisecondes (ici 10).

Mes modifications

Le HTML

La seule modification côté HTML fut de me débarrasser de ce CSS inline tout moche tout pas beau qui sens trop fort le Web 1.0.

Le CSS

Les deux premières règles de ce nouveau CSS sont là pour mettre la div englobante en positionnement relatif et les divs internes en positionnement absolu. Le positionnement relatif de la div englobante permet que ses enfants soient positionnés par rapport à elle, car le positionnement absolu se fait par rapport au plus proche parent positionné de manière relative (voir sur MDN web docs).

#menu {
    position: relative;
}
#menu > div {
    position: absolute;
}

Attention : du fait de l’utilisation du positionnement absolu, tous les éléments du menu sont en dehors de leur div parente et s’affichent au-dessus des éléments de la page plus bas que celle-ci. Il faut bien penser à forcer les dimensions de la div parente si vous souhaitez utiliser ce menu sur votre site.

Viennent ensuite 3 règles pour la mise en forme de l’image centrale du menu.

#menu > #teh {
    left:113px;
    top:54px;
    width:150px;
    height:96px;
    visibility:visible;
    z-index:4;
}
#menu > #teb {
    left:115px;
    top:150px;
    width:150px;
    height:68px;
    visibility:visible;
    z-index:2;
}
#menu > #teh img, #menu > #teb img {
    width: 100%;
    height: 100%;
}

Et pour terminer, 2 règles pour la mise en forme des liens.

#menu > .link {
    left:0px;
    top:0px;
    width:40px;
    height:40px;
    visibility:hidden;
    z-index:3;
}
#menu > .link img {
    width: 39px;
    height: 48px;
}

Le JavaScript

Ici, pas mal de choses ont bougées, le JavaScript ayant beaucoup évolué depuis la création du script original.

Premier gros changement, l’ensemble du code a été englobé d’un EventListener à l’écoute du chargement complet de la page (tout comme le $(document).ready() de jQuery).

window.addEventListener('load', () => {});

L’ajout de cet EventListener a nécessité la réécriture de la fonction en charge du déplacement des éléments du menu en lui rajoutant des paramètres d’entrée.

function rotateObjets(objets, pos, inc, ra, rb) { 
  for (let i = 0; i < pos.length; i++) {
      pos[i] += inc;
      objets[i].style.left = (ra * Math.cos(pos[i])) + 159 + "px";
      objets[i].style.top = (rb * Math.sin(pos[i])) + 94 + "px";
      objets[i].style.visibility = "visible";
  }
} 

Deuxième changement important : l’utilisation de querySelectorAll() pour construire le tableau d’éléments du menu (cette méthode n’est supportée que depuis 2009 au plus tôt, d’où ce changement assez conséquent).

let objets = document.querySelectorAll('#menu > .link');

Le dernier changement se situe dans la manière d’assurer l’appel en boucle de la fonction de déplacement des entrées du menu. Au lieu d’utiliser un Timeout à la fin de la fonction à appeler en boucle, j’utilise un setInterval.

let rotateTimer;

rotateObjets(objets, pos, inc, ra, rb);
rotateTimer = window.setInterval(rotateObjets, 10, objets, pos, inc, ra, rb);

Ce setInterval est très utile pour la seule fonctionnalité ajoutée : l’arrêt de la rotation quand la souris survole un des éléments du menu.

Cette nouvelle fonctionnalité est assurée par l’ajout de deux eventListeners sur les éléments du menu : un pour quand la souris arrive sur l’élément, et un autre quand elle le quitte.

objets.forEach((objet) => {
  objet.addEventListener('mouseenter', (e) => {
    clearInterval(rotateTimer);
  });

  objet.addEventListener('mouseleave', (e) => {
    rotateObjets(objets, pos, inc, ra, rb);
    rotateTimer = window.setInterval(rotateObjets, 10, objets, pos, inc, ra, rb); 
  });
});

Le premier événement supprime la boucle avec clearInterval().

Le deuxième relance le mecanisme.

Pour conclure

J’espère que cet article vous aura été utile tout comme mes précédents tutoriels.

Pour voir le script en action et accéder au code source, rendez-vous ici.

Laisser un commentaire