PiHomeDashScreen – 13 – Faire tomber la neige

snowL’hiver arrive, et avec lui, espĂ©rons-le, la neige 🙂 J’aime beaucoup la neige, c’est joli, et c’est trĂšs relaxant de regarder tomber les flocons dans le calme 🙂

Sur un Ă©cran, l’effet est le mĂȘme 🙂 J’utilise depuis longtemps Xsnow sur mon bureau. C’est old-school au niveau du design, mais c’est charmant de voir la neige s’amasser au desssus des fenĂȘtres du bureau 🙂 Je n’ai malheureusement pas trouvĂ© le moyen de faire tomber les flocons de neige de Xsnow « au premier plan » c’est Ă  dire devant la fenĂȘtre du navigateur qui affiche les donnĂ©es du dashscreen.

J’ai testĂ© de nombreuses lib javascript permetant de faire tomber de la neige sur des pages web. Certaines sont rĂ©ellement trĂšs jolies : http://www.jqueryrain.com/2012/04/top-jquery-snow-falling-effect-plugin-tutorial-with-example/

En revanche, ces lib sont relativement gourmandes en ressource. MĂȘme si les scripts ne pĂšsent que quelques disaines de Ko pour les plus lĂ©gĂšres, leur exĂ©cution en demande beaucoup au petit processeur du Pi 🙁

Je vous propose donc aujourd’hui un tout petit module en JavaScript permettant de faire illusion sans mettre Ă  genoux le Pi 🙂 Pour l’activer sur votre dashscreen, vous devrez modifier les fichiers style.css et javascript.js comme suit :

style.css

La feuille de style permet de définir le style des <div> qui contiennent les flocons :

/* snow */

div.snow
{
  position          : absolute;
  width             : 1px;
  height            : 1px;
  font-weight       : bold;
  color             : #FFF;
  z-index           : 99999;
}

javascript.js

Inutil de créer une <div> dédiée dans la page index.php, nous utiliserons la div « main » comme conteneur.

/* snow */

var nb_flakes = 40;      // nombre de flocons
var speed     = 15000;   // vitesse en ms +- 5 secondes
var size      = 1;       // taille des flocons

function snowFall (id) {
  var duration = Math.floor((Math.random()*5)+1)*1000+speed;
  var left = Math.floor((Math.random()*200)+1);
  $("#"+id).animate({
    top: "+=760",
    left : "+="+left
  },
  duration,
  function() {
    var flake_size = Math.floor((Math.random()*20)+10*size);
    var left = Math.floor((Math.random()*1360)+1);
    $(this).css('top', -20).css('left', left).css('font-size', flake_size);
    snowFall(id);
  });
}

function snow () {
  for(var i=0;i<=nb_flakes;i++) {
    var left = Math.floor((Math.random()*1360)+1);
    var flake_size = Math.floor((Math.random()*20)+10*size);
    $("#main").append('<div class="snow" id="s'+i+'" style="left : '+left+'px; font-size : '+flake_size+'px; ">*</div>');
    snowFall("s"+i);
  }
}

La fonction snow() va crĂ©er des <div> contenant des « * » (pour reprĂ©senter les flocons de neige) de tailles diffĂ©rentes et va les ajouter dans la div « main« . Puis pour chaque <div> « flocon« , la fonction snowFall() va les faire dĂ©filer de haut en bas a des vitesses diffĂ©rentes et selon des angles diffĂ©rents donnant l’illusion d’une vĂ©ritable chute de neige 🙂

 

8 rĂ©flexions au sujet de « PiHomeDashScreen – 13 – Faire tomber la neige »

  1. tchou

    Tu dĂ©clare une class CSS snow, mais tu ne l’utilise pas dans ton script ni dans ton HTML … ?

    Pour rajouter un effet, pourquoi pas utiliser diverses typos pour les astérisques, voire créer une typo dédiée avec 3-4 flocons et tu boucle sur ceux-ci ? Créer une typo se fait assez rapidement genre avec icomoon.io

    Y’a moyen d’optimiser ton script car mĂȘme plus lĂ©ger que l’extrĂȘme majoritĂ© des plugins JS, je vois clairement sur ma machine actuelle (certes vieille) mes cpumetres s’affoler en testant ton script, donc un raspberry … ! 🙂
    La manipulation du DOM est une opĂ©ration coĂ»teuse en temps machine. En gros, tu boucle 40 fois en demandant Ă  jQuery de rechercher un noeud ET de lui rajouter un fils. Si tu stockait le paquet de fils dans un coin (une variable qu’on appelerai orphelinat ou mere_celibataire ! 🙂 ) et que tu recherchait oĂč es $(‘#main’) et lui coller la progĂ©niture une seule fois, ça devrai aller mieux. De la mĂȘme maniĂšre, snowfall() attend une variable string pour chercher dans la DOM cet id, en resortir un objet jQuery qu’il anime, puis reprend la string et la renvoie Ă  lui-mĂȘme. Si tu cherchait une fois l’objet jQuery pour l’obtenir, plus besoin de le rechercher pour la suite (opĂ©ration coĂ»teuse en temps cpu), la fonction reçoit directement un objet jQuery manipulable !

    Dans snow(), tu change l’appel Ă  snowFall par snowFall($(« #s »+i)) , et dans snowFall tu replace ta ligne $(« # »+id).animate par id.animate et basta j’ai quasi rien changĂ© Ă  ta fonction mais elle devrai ĂȘtre moins gourmande.

    1. Olivier Auteur de l’article

      Hello tchou,

      Avant tout, merci pour ton retour et toutes ces prĂ©cisions 🙂

      J’ai effectivement oubliĂ© d’utiliser la class « snow », je viens de corriger le code source 🙂

      En terme d’optimisation, je ne suis pas satisfait de mon script car comme tu le dis, il reste gourmand en ressource. Sur le Pi, mĂȘme avec seulement 30 flocons, ca ramouille sĂ©vĂšre 🙁

      Pour la fonction snow() qui invoque les div contenant les flocons, Ă©tant donnĂ©e qu’elle n’est appelĂ©e qu’une fois au chargement de la page, cela ne devrait pas jouer sur la fluiditĂ© de l’animation. Si ?
      Si je comprends bien ce que tu propose, il s’agirait de crĂ©er directement les div flocons (avec une boucle PHP par exemple), plutĂŽt que de les ajouter une par une dans la div « main ». C’est bien ça ?

      Pour la fonction snowFall(), je n’ai pas trop compris ce que tu proposes de faire. Est ce que tu peux dĂ©tailler un peu plus stp ?

      Si tu peux passer 5 minutes Ă  rĂ©Ă©crire la fonction pour obtenir une implĂ©mentation plus lĂ©gĂšre, et la poster en commentaire, ce serait vraiment sympa de ta part 🙂

      En tout cas, merci bcp pour ces infos et recommendations 🙂

  2. tchou

    Si l’Ă©cran ne se reload jamais, comme dans le cas bien spĂ©cifique de ton dashscreen, c’est vrai que la perte de temps initiale est moins pertinente. Et pour info, non, la boucle Ă©tait en JS aussi.

    Copier-coller du code (js) dans ce commentaire, j’ai comme dans l’idĂ©e que wordpress va me saborder le code comme il a dĂ©jĂ  commencĂ© Ă  le faire dans mon commentaire prĂ©cĂ©dent autour des guillemets.

    J’ai peut ĂȘtre une idĂ©e pour rendre ça plus lĂ©ger … tu me confirme que ton homedashscreen n’a qu’une vocation d’affichage, tu n’as pas Ă  agir directement dessus (cliquer, toucher, Ă©crire dans un formulaire, …) ? En gros, est-ce que ça dĂ©range si je colle un calque par dessus ? J’ai p’t’et’ une idĂ©e, et ça m’intĂ©resse de savoir ce que ça donne en terme de perfs (surtout sur un Rpi). Je fais ça Ă  temps perdu et je te fais passer.

    1. tchou

      Se rĂ©pondre Ă  soi-mĂȘme … quelle vanitĂ©, pfff !

      Bon, y’a plein de gens qui ont dĂ©jĂ  inventĂ© la roue, donc je ne l’ai pas refaite. Mais en test rapide, ouais, utiliser 2000/2500 particules « flocons » en canvas me met ma machine approximativement autant laggy que 100 insĂ©rĂ©es en DOM … donc :
      a) j’ai honteusement pompĂ© le premier lien « snow canvas html5 » que j’ai trouvĂ© … enfin, le second, car le premier c’Ă©tait juste trop beau mais trop gourmand ( http://seb.ly/2010/11/javascript-html5-canvas-snow-in-3d/ ce type est un gĂ©nie). Or donc le premier (mais non l’unique), c’Ă©tait : http://thecodeplayer.com/walkthrough/html5-canvas-snow-effect

      b) Pomper honteusement le tout et coller dans ta page, en rajoutant juste au dĂ©but de l’infùùùme c+c/c+v une insertion de la balise en js (ou le mettre en dur dans ton html) :
      $(‘#main’).append( »);

      En CSS, tu positionne #canvas en absolute avec un top et un left Ă  0

      Et voilĂ , quick&dirty tu devrai avoir des flocons de neige animĂ©s dans un canvas transparent posĂ© au dessus de tes infos. L’inconvĂ©nient Ă©tant que tu ne peux plus cliquer sur ce qu’il y a dessous, mais dans ton application ça devrai ne pas poser soucis.

      AprĂšs, suffit d’amĂ©liorer l’effet, avoir un effet bourrasque donc pas la mĂȘme direction ni la mĂȘme vitesse pour chaque particule/flocon en introduisant du random, mais dĂ©jĂ  tu as une base qui Ă  mon avis devrai ĂȘtre bien moins lourde pour le petit raspberry.
      En sachant que chaque particule peut ĂȘtre autre chose qu’un rond, bien sĂ»r. Tu peux animer des images ou du texte de cette façon. J’avais il y a longtemps pour un pari Ă  la con animĂ© 2000 images rebondissantes, ça se fait trĂšs vite en canvas : http://jsfiddle.net/92sTD/ (warning: grosse connerie inside, pas forcĂ©ment trĂšs safe for workspace ! 🙂 )

    2. Olivier Auteur de l’article

      Le dashscreen n’a effectivement que vocation Ă  afficher des donnĂ©es sans interactions directes possibles.

  3. Jean-François

    Merci, Tchou, pour ta version qui marche bien (mĂȘme si elle est « quick&dirty » ;o)), cela dit, l’animation reste beaucoup plus lente que sur un PC standard et ça ne semble donc pas dĂ©charger tant que ça le RPi…
    Quant Ă  la solution d’Olivier, elle marche finalement pas si mal (avec ou sans la modif. proposĂ©e par Tchou dans son premier commentaire), mais sur mon afficheur, si les flocons « sortent » de l’Ă©cran, des ascenseurs apparaissent sur les bords… grrrr !

    Merci encore pour ce beau travail !

  4. Ping : 12 – En rĂ©sumĂ© | MagdiBlog

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.