Réaliser un Google Doodle

Par , le , dans Tutoriels 4

Bonjour à tous ! Aujourd’hui nous allons parler Doodle. Alors qu’est-ce que le Google Doodle pour ceux qui n’en ont jamais entendu parler ? Le Google Doodle est une adaptation temporaire du logo de Google sur sa page d’accueil. Cette version modifiée est affichée pendant une journée et elle célèbre des événements, anniversaires ou encore fêtes nationales. Ces derniers temps, Google innove de plus en plus sur la technologie de ses Doodles avec HTML5, CSS3 et Javascript. Les animations n’utilisent pas Flash, mais ont un rendu néanmoins impressionnant.

Nous allons voir ensemble comment réaliser le Doodle du 117ème anniversaire de Martha Graham’s du 11 Mai 2011. Ce Doodle est une animation de Ryan Woodward dont vous pouvez avoir un aperçu de ses travaux sur son site www.ryanwoodwardart.com. Il faut savoir que tous les Doodles sont conçu différemment et la technique utilisée pour réaliser celui-ci n’est pas à 100% celle utilisée par Google mais en reprend les grandes lignes.

Retrouvez le rendu final à cette adresse : Rendu final du Google Doodle

Etape 1 : Les bases de l’animation

Toute notre scène va se dérouler dans un rectangle de 403px de large par 156px de hauteur. Nous allons donc créer une div que nous appellerons logo_start avec un id, elle sera notre scène. Il nous faut ensuite 2 images. Une qui représente la première image de l’animation, puis un sprite qui contient toutes les images de l’animation. Il vous faudra aussi installer en local ou faire appel à la bibliothèque JQuery.

Image de départ : img_start.png
Sprite : img_sprite.png
Jquery : jquery-1.6.1.min

Une fois les documents ci-dessus récupérés, attaquons le HTML et le CSS de notre Doodle :

<div id="logo_start"></div>
#logo_start{
  position:relative;
  width:403px;
  height:156px;
  background:url('img_start.png') no-repeat top left;
}

On place la div en position : relative afin de pouvoir jouer avec les positions : absolute à l’intérieur.

Voilà, c’est tout pour le HTML et le CSS de notre animation, tout le reste va se dérouler côté Javascript.

Etape 2 : Les bases du Javascript

Avant d’entamer le Js, je vais essayer d’être le plus clair possible sur ce que nous allons tenter de réaliser. Le principe de base est de faire apparaître des div dans cette scène. Chaque div a ses propres coordonnées de positionnement par rapport au point haut gauche de logo_start et chaque div a une image de fond bien précise. Ces images de fond sont toutes réunies sur le sprite que vous avez récupéré plus haut.

Nous avons donc pour chaque image de l’animation, des coordonnées de placement et des coordonnées pour l’image de fond. Les div apparaissant au bon endroit, avec le bon fond, feront apparaître l’animation. Il y a environ 155 images a faire apparaître pour jouer toute l’animation. Je vous entends déjà : « les tableaux de coordonnées vont être interminables ! » Et bien oui, mais rassurez-vous, nous avons déjà tout calculé pour vous, se sera l’affaire d’un simple copier/coller.

Attaquons donc notre fichier JS et commençons par les fameux tableaux de coordonnées :

var d = [307,48,88,89,307,48,89,89,307,48,91,89,305,49,93,89,305,50,93,88,305,50,93,88,306,52,92,86,305,53,93,84,305,54,94,83,306,54,93,83,307,54,92,83,307,54,92,83,308,54,90,83,308,54,90,83,306,53,91,84,306,53,91,84,308,53,90,84,308,53,90,84,305,53,92,84,305,52,92,85,306,52,91,85,308,51,88,87,308,50,88,88,308,49,88,88,307,49,89,88,307,50,89,87,308,51,89,86,307,54,90,83,307,57,90,80,306,58,92,79,306,58,92,79,305,60,92,77,302,61,95,76,302,63,95,74,302,51,96,86,302,66,98,71,304,67,96,69,301,63,96,74,301,58,93,79,291,52,94,85,288,50,71,88,285,43,76,95,285,37,70,101,281,29,55,109,278,20,58,119,278,20,55,119,277,12,121,127,271,2,122,138,267,1,126,139,264,0,136,140,260,0,141,140,255,0,148,140,252,0,151,140,249,2,121,138,247,3,123,137,246,3,123,137,246,2,124,137,258,2,112,137,263,2,106,137,263,2,106,137,262,2,103,137,260,2,104,136,260,2,104,137,268,2,98,137,267,2,99,137,266,2,97,137,266,3,96,136,264,3,99,136,263,3,100,136,261,3,100,136,259,2,138,137,254,2,126,137,247,2,101,136,240,2,108,136,238,1,110,137,230,1,118,138,220,15,128,124,211,18,137,121,205,43,102,96,202,45,104,93,200,38,97,101,198,38,104,101,197,39,107,100,197,39,112,100,213,39,94,110,212,40,95,111,211,41,97,111,209,42,99,112,209,43,98,112,213,43,87,112,213,42,83,113,211,40,86,109,211,38,86,103,211,37,88,112,211,20,186,131,213,27,167,122,212,44,87,105,210,44,88,98,195,44,106,98,189,44,110,98,182,46,117,99,173,44,118,96,161,43,130,99,154,42,137,97,153,42,137,97,153,42,137,97,152,41,137,98,151,41,137,97,149,41,145,97,148,25,144,114,148,13,144,126,141,12,153,127,115,11,173,128,108,7,180,133,108,4,180,136,108,3,176,137,108,1,161,139,105,1,235,138,103,1,295,148,103,0,277,149,108,0,234,137,101,0,232,137,99,0,135,139,95,0,244,139,81,0,152,139,69,0,164,139,66,0,169,139,65,0,170,139,63,0,168,138,61,0,159,138,35,0,304,139,19,0,189,140,18,11,138,129,18,11,137,129,18,11,137,128,18,6,135,133,7,4,146,136,6,4,147,136,3,4,150,136,3,5,150,135,3,8,150,132,4,6,394,145,12,6,388,145,11,8,389,144,11,8,387,144,11,8,387,143,10,8,113,131,11,8,111,131,10,9,112,130,12,9,116,130,12,9,111,130,12,9,111,130,12,9,110,131,12,34,113,106,13,35,110,104];

var e = [0,0,-88,0,-177,0,-268,0,-361,0,-454,0,-547,0,-639,0,-732,0,-826,0,-919,0,-1011,0,-1103,0,-1193,0,-1283,0,-1374,0,-1465,0,-1555,0,-1645,0,-1737,0,-1829,0,-1920,0,0,-89,-88,-89,-176,-89,-265,-89,-354,-89,-443,-89,-533,-89,-623,-89,-715,-89,-807,-89,-899,-89,-994,-89,-1089,-89,-1185,-89,-1283,-89,-1379,-89,-1475,-89,-1568,-89,-1662,-89,-1733,-89,-1809,-89,-1879,-89,-1934,-89,-1992,-89,0,-208,-121,-208,-243,-208,-369,-208,-505,-208,-646,-208,-794,-208,-945,-208,-1066,-208,-1189,-208,-1312,-208,-1436,-208,-1548,-208,-1654,-208,-1760,-208,-1863,-208,-1967,-208,0,-348,-98,-348,-197,-348,-294,-348,-390,-348,-489,-348,-589,-348,-689,-348,-827,-348,-953,-348,-1054,-348,-1162,-348,-1272,-348,-1390,-348,-1518,-348,-1655,-348,-1757,-348,-1861,-348,-1958,-348,0,-486,-107,-486,-219,-486,-313,-486,-408,-486,-505,-486,-604,-486,-702,-486,-789,-486,-872,-486,-958,-486,-1044,-486,-1132,-486,-1318,-486,-1485,-486,-1572,-486,-1660,-486,-1766,-486,-1876,-486,-1993,-486,0,-617,-130,-617,-267,-617,-404,-617,-541,-617,-678,-617,-815,-617,-960,-617,-1104,-617,-1248,-617,-1401,-617,-1574,-617,-1754,-617,-1934,-617,0,-754,-161,-754,-396,-754,-691,-754,-968,-754,-1202,-754,-1434,-754,-1569,-754,-1813,-754,-1965,-754,0,-903,-169,-903,-339,-903,-507,-903,-666,-903,-970,-903,-1159,-903,-1297,-903,-1434,-903,-1571,-903,-1706,-903,-1852,-903,-1999,-903,0,-1043,-150,-1043,-300,-1043,-694,-1043,-1082,-1043,-1471,-1043,-1858,-1043,0,-1188,-113,-1188,-224,-1188,-336,-1188,-452,-1188,-563,-1188,-674,-1188,-784,-1188,-897,-1188];

On vous avait prévenu, les tableaux sont costaux ! Mettez-les en début de fichier et faites une mise en forme qui ne vous gênera pas trop pour la suite.

Le tableau d définit les coordonnées de placement et de dimension des div. Afin de bien comprendre le fonctionnement de ce tableau, prenons les 4 premières données. 307 correspond au positionnement gauche, 48 correspond au positionnement haut, 88 le nombre de pixels de largeur et 89 les pixels de hauteur. Nous avons donc créé une div qui se placera sur la scène comme ceci :

Le tableau e définit les coordonnées du sprite des images de fond des div.

Nous allons définir les variables dont nous allons avoir besoin :

var i = 0;
var j = 0;
var temp = 0;

i correspondant au pointeur qui va parcourir le tableau d et j celui qui va parcourir le tableau e. temp correspond au compteur d’image. Dans notre Timer, une fois arrivé à 155 images, nous arrêterons l’animation, mais nous verrons cela plus tard.

Etape 3 : Les fonctions du Javascript

Passons maintenant au côté pratique. Nous allons lancer une fonction qui s’appelle Image à l’ouverture de notre page. Nous utiliserons simplement l’appel une fois que JQuery sera chargé. Nous avons donc le code suivant :

$(function() {
	Image();
});

Détaillons maintenant cette fonction Image. Je vous la donne et nous la commenterons après :

function Image(){

	temp++;

	var left = d[i];
	i++;
	var top = d[i];
	i++;
	var width = d[i];
	i++;
	var height = d[i];

	var y = e[j];
	j++;
	var x = e[j];
	j++;

	$("#logo_start").append("<div style='position:absolute; left:"+left+"px; top:"+top+"px; width:"+width+"px; height:"+height+"px; background-image:url(img_sprite.png); background-position:"+y+"px "+x+"px;'></div>");
	i++;
	Timer();
}

Allons-y ligne par ligne.

  • temp++ va incrémenter temp de 1. Nous aurons ainsi un indicateur pour savoir à quelle image nous nous trouvons à chaque moment de l’animation.
  • var left = d[i] récupère la première coordonnée de positionnement de la div que nous allons créer, ici le nombre de pixels à gauche par rapport au coin haut gauche de la div logo_start.
  • var top = d[i] récupère la valeur top de la div de la même manière que left vu précédemment. Nous avons incrémenté i avec i++ afin de passer à la valeur suivante dans le tableau d.
  • var width et height récupèrent eux les dimensions de la div que nous allons créer.
  • var y = e[j] récupère les coordonnées en y du sprite pour afficher la bonne image de fond dans notre div.
  • var x = e[j] va nous donner les coordonnées en x.

Voilà, nous avons tous les renseignements pour créer notre div. Ses dimensions width et height, sa position left et top, ainsi que le background-position du sprite. Nous pouvons donc enfin la créer avec un append de la librairie JQuery. Append va créer un élément HTML dans une balise ciblée à la suite du code existant. Nous aurons donc pas moins de 155 div à l’intérieur de logo_start à la fin de l’animation.

Allons-y :

  • $(‘#logo_start‘) cible la div logo_start en JQuery
  • append() ajoute donc le html que nous allons lui définir à la suite que ce qui existe déjà dans logo_start.
  • Nous créons une simple div que nous stylisons directement avec l’attribut style. Donc position à absolute avec left et top que nous avons récupéré du tableau d. Width et height que nous avons récupérés aussi de d. Puis le background-image du sprite ainsi que ses coordonnées avec background-position que nous avons cette fois récupérés du tableau e.

Pour finir avec la fonction Image, nous faisons appel à un petit Timer qui va temporiser de 50ms entre chaque image notre animation. Nous faisons également un petit test sur la variable temp pour savoir si nous sommes arrivés à 155 images. Si l’animation n’est pas finie, ont envoi le Timer de 50ms qui appellera à nouveau la fonction Image qui dessinera l’image suivante, sinon on arrête tout car l’animation est finie.

Voici le code de la fonction Timer :

function Timer(){
	if(temp!=155){
		setTimeout("Image()",50);
	}
	else{
		return false;
	}
}

Voilà, vous avez tous les éléments de l’animation. Votre animation devrait s’afficher correctement.

On peut ensuite ajouter un bouton de lancement de l’animation. Pour cela il suffit de mettre l’événement sur un clic dans la partie JQuery. On peut par exemple avoir comme événement :

$("#monbouton").click(function(){
	Image() ;
}) ;

Note : Il faut penser à réinitialiser toutes les variables pour repartir d’une animation vierge.

Conclusion

Nous avons vu grâce à la création de ce Doodle que Google utilise des techniques à la portée de tous pour réaliser de très belles animations. Ils poussent cependant la technique avec l’utilisation d’un sprite et surtout de tout un tas de coordonnées à calculer avec une extrême précision.

La conception de ce Doodle est très intéressante car elle permet de voir toutes les étapes de fabrication d’une telle animation. Le graphiste doit réaliser toutes les images du sprite en tenant compte de la technique des append utilisée. Les développeurs doivent calculer toutes les coordonnées. Tout cela pour une animation de 5-6 secondes. Flash n’est donc pas une technologie morte, mais Google nous prouve une fois de plus que les autres technologies ont fait un grand pas en avant ces dernières années afin de réaliser de très belles animations.

Discutons-en…

Nous avons réalisé ce Doodle de cette manière, auriez-vous fait autrement, quelles améliorations voyez-vous en terme technique ? Tous vos avis nous intéressent, n’hésitez pas à en discuter en postant un commentaire.

Commentaires

  1. Artusamak

    On a pas le droit à l’aperçu final du rendu ? =)

  2. Si si, le lien est juste au-dessus de l’Etape 1.

  3. Floby

    à noter que nommer notre fonction Image n’est peut-être pas une bonne idée. C’est aussi le nom d’une fonction native permettant de crée des éléments . Certain navigateurs n’autorisent pas ce genre de surcharge.

    Bien sûr si tout notre fichier javascript est contenu dans un fonction auto-appelante, ceci n’est plus un problème.

  4. Effectivement le nommage n’est pas optimisé. Le but était de faire simple et compréhensible. Bien que je t’avoue ne pas avoir trouvé la fonction image dont tu parles.

    Il faut évidemment pas mettre non plus des noms de variables type i ou j.

    Ceci est un exemple, à chacun de personnaliser cette base de code ;)

Obligatoire

Obligatoire