Partage
  • Partager sur Facebook
  • Partager sur Twitter

Lumière qui suit la souris

    10 octobre 2020 à 12:24:57

    Bonjour,

    Je souhaite faire une lumière qui suit la souris et affiche les éléments cachés dans un div de fond noir quand on passe dessus.

    Je comprends bien que mon code actuel se contente de suivre un div de fond blanc sur un autre de fond noir. Le but étant de "faire un trou" blanc dans le div de fond noir. Mais je n'y arrive pas et ça fait des heures que je suis dessus. Je ne veux pas de lien vers un code tout fait, j'aimerais des explications précises de comment ça marche si possible.

    En espérant avoir été clair dans mes explciations.

    Code html :

        <div id="content" class="enigme">
    
          <div class="informations">
            <h1>Éclaircissons les choses avec un tuto</h1>
            <p>Description : Trouve le texte !</p>
          </div>
          
          <div id="board" class="enigme1 board">
            <h2 class="text">Tu m'a trouvé !</h2>
          </div>
          
            <div id="light"></div>
    
        </div>


    css :

    #board
    {
      display: flex;
      justify-content : center;
      align-items: center;
      background-color: black;
      flex:0.92;
    }
    
    #light
    {
      position: fixed;
      top: 0;
      left:0;
      width: 200px;
      height: 200px;
      pointer-events: none;
      background-color: white;
      opacity: 50%;
      border-radius: 100%;
    }
    
    .text
    {
      display: flex;
      color: black;
    }
    

    Jquery:

    $(function()
    {
      $('#board').mousemove(function(e)
      {
        $('#light').css('visibility','visible');
        var light = $('#light');
        var x = e.pageX;
        var y = e.pageY;
        light.css({
          top: (y - 100) + "px",
          left: (x - 100) + "px"
        });
      });
    
      $('#board').mouseout(function()
      {
        $('#light').css('visibility','hidden');
      });
    
    
    });// Fermeture declaration jquery
    


    Merci d'avance et bonne journée.

    • Partager sur Facebook
    • Partager sur Twitter
      10 octobre 2020 à 13:17:00

      Salut,

      La méthode avec svg et clipPath :

      • 1) Tu supprime ton élément light. Il t'induit en erreur car tu n'a pas besoin de cette élément pour obtenir ton effet.
      • 2) Tu ajoutes quelque part dans ton DOM (peu importe où) un élément svg de ce genre :
        <svg class="svg-defs">
            <defs>
                <clipPath id="clip-path" clipPathUnits="objectBoundingBox">
                    <rect x="0" y="0" width="100%" height="100%" clip-rule="evenodd" />
                    <circle cx="-200" cy="-200" r="200" clip-rule="evenodd" />
                </clipPath>
            </defs>
        </svg>
        avec une class 'svg-defs' dans ton css qui décrit ton élément 'svg' de la sorte :
        .svg-defs {
            display: block;
            position: absolute;
            opacity: 0;
            pointer-events: none;
        }
        Pourquoi ? Parce que tu vas avoir besoin que le navigateur effectue le rendu de ton svg sans qu'il soit visible à l'écran, ni qu'il soit possible d'interagir avec.
      • 3) Tu ajoutes la propriété css 'clip-path' avec la valeur 'url(#clip-path)' à ta règle css '#board'. Ca va permettre de mettre en place le "masque" qui va suivre ta souris sur le '#board'.
      • 4) Tu peux également ajouté la propriété 'will-change' avec la valeur 'clip-path' à ta règle '#board' si tu constate des problèmes de lag sur le rendu, car modifier la propriété clip-path peut ne pas être pas top question performance sur le rendu du navigateur. Ca permet donc de prévenir le navigateur que la propriété va changer régulièrement et de ce préparer à gerer la chose.
      • 5) Tu modifies avec javascript les positions 'cx' et 'cy' de l'élément 'circle' de sorte à ce que ça suive la souris par rapport à la position de l'élément '#board'.

      -
      Edité par BrainError 11 octobre 2020 à 8:44:08

      • Partager sur Facebook
      • Partager sur Twitter
        10 octobre 2020 à 14:38:03

        Bonjour,

        merci ^^

        Je ne connaissais pas du tout ça, et ça à l'air plutôt bien, même si je ne comprends pas grand-chose pour l'instant :

        HTML :

          <svg class="svg-defs">
            <defs>
              <clipPath id="clip-path">
                <circle class="circle" cx="" cy="" r="100" fill="red"/>
              </clipPath>
            </defs>
          </svg>


        CSS :

        #board
        {
          display: flex;
          justify-content : center;
          align-items: center;
          background-color: white;
          flex:0.92;
          clip-path: url(#clip-path);
        }
        
        .svg-defs
        {
          display: block;
          position: absolute;
          opacity:0;
          pointer-events:none;
        }

        JS

        $(function()
        {
          $('#board').mousemove(function(e)
          {
            var offset = $(this).offset();
            var x = e.clientX - offset.left;
            var y = e.clientY - offset.top;
            $("circle").attr('cx',x);
            $("circle").attr('cy',y);
          });
        
        });



        J'ai du mal à saisir ta phrase " le rendu de ton svg sans qu'il soit visible à l'écran".

        Techniquement je veux qu'il soit visible, je veux voir apparaitre un rond blanc. Je suis aller un peu m'informé, j'ai rajouter des trucs, enlever des trucs, mais rien ne s'affiche.

        Je continue de m'informé dessus parce que ça à l'air vraiment pratique tout ça, mais je veux bien un peu d'aide ^^

        UPDATE : J'ai finalement réussi, j'ai pas encore tout compris, et je serai incapable de le refaire demain, mais j'ai réussi. J'ai mis le nouveau code.

        Par contre j'ai encore un léger problème, c'est que si on va trop vite avec la souris, le cercle ne suit pas et bug. J'ai tenté avec la propriété will-change mais ça ne change rien.

        -
        Edité par Navarog 10 octobre 2020 à 16:30:59

        • Partager sur Facebook
        • Partager sur Twitter
          11 octobre 2020 à 9:08:06

          Salut,

          Quand je te parlais de rendu sans visibilité, je veux dire par là que si tu définis la propriété css 'display' sur 'none' pour l'élément svg : le navigateur va purement et simplement omettre le rendu de l'élément, ce qui aura pour conséquence d'avoir un élément 'clipPath' qui ne sera pas rendu non plus et qui ne pourra pas être utiliser dans la propriété css 'clip-path'.

          En définissant 'display' sur 'block' mais en masquant l'élément grâce à 'opacity: 0;' et en le rendant inerte avec 'pointer-events: none;', tu dis au navigateur de procéder au rendu de quelque chose qui ne sera pas visible et avec lequel il sera impossible d'interagir. C'est important car même si le navigateur n'affiche rien, pour lui, il y a quand même bien eu un rendu de l'élément ce qui lui permet donc d'être utilisable pour 'clip-path'.

          Une autre solution qui m'est venu plus tard ; plus simple (sans svg) et sans doute moins casse pied à mettre en place :

          https://codepen.io/brainerror/pen/zYBxgVj

          -
          Edité par BrainError 11 octobre 2020 à 9:10:06

          • Partager sur Facebook
          • Partager sur Twitter
            13 octobre 2020 à 13:13:29

            Magnifique, à plus d'un titre, le coup du text.style.setProperty('--top', e.clientY - rect.y + 'px') !

            Je retiens !

            • Partager sur Facebook
            • Partager sur Twitter
              14 octobre 2020 à 16:15:21

              BrainError a écrit:

              Salut,

              Quand je te parlais de rendu sans visibilité, je veux dire par là que si tu définis la propriété css 'display' sur 'none' pour l'élément svg : le navigateur va purement et simplement omettre le rendu de l'élément, ce qui aura pour conséquence d'avoir un élément 'clipPath' qui ne sera pas rendu non plus et qui ne pourra pas être utiliser dans la propriété css 'clip-path'.

              En définissant 'display' sur 'block' mais en masquant l'élément grâce à 'opacity: 0;' et en le rendant inerte avec 'pointer-events: none;', tu dis au navigateur de procéder au rendu de quelque chose qui ne sera pas visible et avec lequel il sera impossible d'interagir. C'est important car même si le navigateur n'affiche rien, pour lui, il y a quand même bien eu un rendu de l'élément ce qui lui permet donc d'être utilisable pour 'clip-path'.

              Une autre solution qui m'est venu plus tard ; plus simple (sans svg) et sans doute moins casse pied à mettre en place :

              https://codepen.io/brainerror/pen/zYBxgVj

              -
              Edité par BrainError 11 octobre 2020 à 9:10:06


              Salut,

              Effectivement je préfère cette méthode. Par ailleurs je ne savais même pas qu'on pouvais créer des variables en CSS.

              Je reviens te voir car je n'arrive pas à retranscrire ton code en Jquery.

              Je l'ai changé comme ça :

                $('html').mousemove(function(e)
                {
                  var offset = $('#light').offset();
                  var x = e.clientX - offset.left;
                  var y = e.clientY - offset.top;
                  $('#light').css('--left', x);
                  $('#light').css('--top', y);
                });

              Mais ça ne marche pas et je ne comprends pas pourquoi.

              -
              Edité par Navarog 14 octobre 2020 à 16:16:36

              • Partager sur Facebook
              • Partager sur Twitter
                14 octobre 2020 à 17:50:51

                Salut,

                Mais pourquoi ?

                Pourquoi vouloir retranscrire du js pur en JQuery ? Ça n'a pas le moindre sens, laisse moi t'expliquer pourquoi :

                • Premièrement : tu commences par utiliser un selector jQuery pour récupérer ton élément html. Sache que le selector jQuery c'est LENT.
                  Plutôt devrais-je dire "TRES LENT". Voilà un screenshot de comparaison sur ton opération en js pur et jQuery (comparatif du nombre d'opérations sur une seconde, sur les performances de mon pc et avec chrome) :


                  Comme tu peux le voir, js pur est 316.7% plus rapide que jQuery pour la même opération.
                • Par ailleurs, sache qu'en vérité, tu peux accéder à la balise 'html' au moyen de 'document.documentElement'.
                  Voilà pour comparaison avec jQuery :

                  La différence est maintenant de 386,3%.
                • Troisième point : en vérité, si tu n'utilisais pas jQuery, tu pourrais même te permettre d'utiliser le 'document' directement pour porter ton événement 'mousemove'.
                  Pour comparaison, ça donne ça:


                  La différence de performance est maintenant de 417.8%

                Maintenant, comprends bien que je n'ai procédé au comparatif QUE de ta première opération avec jQuery par rapport à du js pur.
                En vérité, chacune de tes actions avec jQuery va donner le même genre de rendu en terme de performance comparé avec js pur.
                Je te laisse tester et calculer la différence total pour le reste si ça te fait plaisir, mais soit sûr que sur une action aussi souvent répété que ton gestionnaire d'événement 'mousemove', la différence de performance à l'arriver est juste suffisamment monumentale pour qu'il soit possible que tu puisse percevoir visuellement là chose (sous forme de lag par exemple, voir de freeze pour des codes un peu plus fournis) sur le rendu du navigateur.

                Tout ça pour dire que je ne comprends pas pourquoi tu cherches à transformer du js pur en jQuery, d'autant qu'ici, jQuery n'apporte aucun polyfill de quoi que ce soit qui puisse ne pas être supporté par les anciens navigateurs. Au passage, beaucoup considère jQuery comme étant entièrement obsolète (de A à Z) et ne l'utilise plus du tout.

                -
                Edité par BrainError 14 octobre 2020 à 17:54:26

                • Partager sur Facebook
                • Partager sur Twitter
                  14 octobre 2020 à 19:15:55

                  Salut,

                  En fait vu que j'ai écrit le reste du code en jQuery, je voulais convertir le tiens aussi, histoire que tout soit écrit avec la même syntaxe.

                  Maintenant c'est vrai que j'avais vu que jQuery était plus trop le framework à utiliser. Mais par contre je ne comprends pas le code que tu as mis, la valeur est plus élevée quand tu testes le JavaScript non ? Donc c'est plus long ? J'ai dû rater quelque chose parce que je ne comprends pas.

                  Mon site en gros c'est des énigmes interactives. J'ai des idées en tête et une vague idée du code, et pour certaines il sera conséquent donc si je peux gagner en performance en changeant de framework je suis preneur. Il y aura de la 3d aussi.

                  J'ai entendu parler de vue.js et React. Je vais faire mes recherches aussi mais comme tu as l'air de t'y connaître je veux bien des conseils.

                  Ce qui est sur c'est que je ne veux pas coder en JavaScript pur, je veux apprendre des frameworks.

                  Merci pour toute ton aide en tout cas, j'apprends énormément grâce à toi.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    14 octobre 2020 à 21:39:53

                    Le code est juste un test de performance assez grossier qui permet de mesuré relativement l'efficacité d'une routine par rapport à une autre en comptant le nombre de foi que le navigateur parvient à la réaliser en une seconde. Plus le nombre d'itération est important, meilleur est la performance de cette routine. Donc oui, JS pur est meilleur a tout point de vue que jQuery, ce qui n'a rien de surprenant puisque jQuery est issue de JS.

                    Pour ce qui est des frameworks, je ne peux pas trop t'aider car je n'en utilise aucun : tu t'adresse à un adepte de la réinvention de la roue :euh:. Toutefois, je trouve le concept de vue.js très impressionnant du point de vu de l'intuitivité, mais une fois encore, je ne l'ai jamais vraiment utiliser.

                    Dit toi bien que tu n'échappera pas au JS pur en passant par des frameworks tel que vue.js ou react puisque, du peu que j'ai pu voir, ils ne changent pas aussi fondamentalement que jQuery la façon dont tu codes ton application.

                    Je souhaite quand même ajouter que JS pur n'est pas si effrayant ni compliquer. Comme beaucoup, j'ai commencé le JS sur jQuery avant de l'abandonner. Mais en vérité, je trouve JS plus intuitif, plus logique et surtout facile à maintenir. Et la documentation MDN est vraiment propre pour t'aider quand tu es confronté à un problème.

                    Pour ce qui est de la 3D, les quelques fois où j'en ai eu besoin, j'ai quand même eu recours à la librairie three.js qui possède une bonne documentation aussi et qui m'a permis de bien comprendre les principaux concept mis en jeux par la 3D. Toutefois, si ce que tu souhaite faire en 3D est faisable en CSS (car CSS apporte une panoplie de propriété et de fonction assez basiques, mais parfois suffisantes pour la 3D), je te suggère d'envisager cette possibilité qui peut-être plus simple à mettre en oeuvre.

                    -
                    Edité par BrainError 14 octobre 2020 à 21:41:47

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Lumière qui suit la souris

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown